题意:给出m条边、起点和终点,从起点开始恰好走过n条边(可以重复),求这n条边加起来的最小值。
分析:首先要知道这题最多只有100个点,然后把点离散化(点的坐标为1-1000)后建立邻接矩阵A。则A的某个点[i,j]表示从点i走一条边到底j的最小权值和。现在要走n条边,从一般的思路来看应该是求A^n然后再处理一下,但这题显然不能这么干。于是我们就把矩阵的乘法改变一下:原本是c[i,j]=sum(a[i,k]*b[k,j]),现在改成c[i,j]=min(a[i,k]+b[k,j])且(0<a[i,k],0<b[k,j])。然后最后输出c[s,e]就好啦。
代码:
type arr=array[1..100,1..100] of longint; var n,m,s,e,i,j,len,x,y,tot:longint; c,d:arr; num:array[1..1000] of longint; procedure jia(a,b:arr); var i,j,k:longint; begin for i:=1 to tot do for j:=1 to tot do c[i,j]:=maxlongint div 3; for i:=1 to tot do for j:=1 to tot do for k:=1 to tot do if (a[i,k]<maxlongint)and(b[k,j]<maxlongint) then if a[i,k]+b[k,j]<c[i,j] then c[i,j]:=a[i,k]+b[k,j]; end; procedure ksm(x:longint); begin if x=1 then exit; ksm(x div 2); jia(c,c); if x mod 2=1 then jia(c,d); end; begin readln(n,m,s,e); for i:=1 to m do begin readln(len,x,y); if num[x]=0 then begin inc(tot); num[x]:=tot; end; if num[y]=0 then begin inc(tot); num[y]:=tot; end; d[num[x],num[y]]:=len; d[num[y],num[x]]:=len; end; for i:=1 to tot do for j:=1 to tot do if d[i,j]=0 then d[i,j]:=maxlongint; c:=d; ksm(n); writeln(c[num[s],num[e]]); end.