原题网址:http://www.lydsy.com/JudgeOnline/problem.php?id=1774
题目简述:求两点之间最短路,特别的,最短路定义为边权和加最大点权。(n
≤
250)
题解:看数据范围,可以考虑Floyd,一般Floyd最外层循环枚举的是最大标号的中转点,在这题中,不妨以点权从小到大的顺序枚举,在中转点点权比两端点点权大的时候,说明中转点是路径上权值最大的点,这时可以更新答案。
const
INF=maxlongint div 3;
var
dis,ans:array[0..251,0..251] of longint;
w,num:array[0..251] of longint;
n,m,q,i,j,k,a,b,l:longint;
procedure swap(var a,b:longint);
var t:longint;
begin t:=a;a:=b;b:=t;end;
procedure sort(l,r:longint);
var
i,j,e:longint;
begin
i:=l;j:=r;e:=w[(l+r)>>1];
repeat
while w[i]<e do inc(i);
while e<w[j] do dec(j);
if not (i>j) then
begin
swap(w[i],w[j]);
swap(num[i],num[j]);
inc(i);dec(j);
end;
until i>j;
if l<j then sort(l,j);
if i<r then sort(i,r);
end;
function min(a,b:longint):longint;
begin if (a<b) then exit(a) else exit(b); end;
begin
read(n,m,q);
for i:=1 to n do
for j:=1 to m do
dis[i][j]:=INF;
for i:=1 to n do
dis[i][i]:=0;
ans:=dis;
for i:=1 to n do read(w[i]);
for i:=1 to n do num[i]:=i;
sort(1,n);
for i:=1 to m do
begin
read(a,b,l);
dis[a][b]:=min(dis[a][b],l);
dis[b][a]:=min(dis[b][a],l);
end;
for k:=1 to n do
for i:=1 to n do
for j:=1 to n do
begin
if (w[k]>=w[i])and(w[k]>=w[j])
then ans[num[i]][num[j]]:=min(ans[num[i]][num[j]],dis[num[i]][num[k]]+dis[num[k]][num[j]]+w[k]);
dis[num[i]][num[j]]:=min(dis[num[i]][num[k]]+dis[num[k]][num[j]],dis[num[i]][num[j]]);
end;
for i:=1 to q do
begin
read(a,b);
writeln(ans[a][b]);
end;
end.