传送门
http://poj.org/problem?id=3114
题目大意
给出n个城市,m条边,如果从A能到B,从B也能到A,他们的通信时间为0. 求从s到t最短的通信时间。
题解
先求scc,然后在scc上跑最短路
我都换成离线处理了……无限TLE中QAQAQ
var
dist,dfn,low,p,id:array[0..505]of longint;
t:array[0..20000]of longint;
z,w:array[0..5000,1..3]of longint;
x:array[0..20000,1..4]of longint;
i,j,k:longint;
n,m,len,scc,a,b,c,q,tt,head,tail,v:longint;
function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end;
procedure initz(a,b,c:longint);
begin
z[len,1]:=b; z[len,2]:=c;
if z[a,3]=0
then z[a,3]:=len else z[z[a,1],3]:=len;
z[a,1]:=len; inc(len);
end;
procedure initw(a,b,c:longint);
begin
w[len,1]:=b; w[len,2]:=c;
if w[a,3]=0
then w[a,3]:=len else w[w[a,1],3]:=len;
w[a,1]:=len; inc(len);
end;
procedure sort(l,r,vv:longint);
var i,j,a,b:longint;
begin
i:=l; j:=r; a:=x[(l+r) div 2,vv];
repeat
while x[i,vv]<a do inc(i);
while a<x[j,vv] do dec(j);
if not(i>j) then
begin
b:=x[i,1]; x[i,1]:=x[j,1]; x[j,1]:=b;
b:=x[i,2]; x[i,2]:=x[j,2]; x[j,2]:=b;
b:=x[i,3]; x[i,3]:=x[j,3]; x[j,3]:=b;
b:=x[i,4]; x[i,4]:=x[j,4]; x[j,4]:=b;
inc(i); dec(j);
end;
until i>j;
if l<j then sort(l,j,vv);
if i<r then sort(i,r,vv);
end;
procedure spfa(a:longint);
var i:longint;
begin
for i:=1 to scc do
dist[i]:=1000000;
dist[a]:=0; head:=1; tail:=2; t[1]:=a; p[a]:=1;
while head<tail do
begin
v:=t[head]; inc(head); tt:=w[v,3];
while tt<>0 do
begin
if dist[v]+w[tt,2]<dist[w[tt,1]] then begin
dist[w[tt,1]]:=dist[v]+w[tt,2];
if p[w[tt,1]]=0 then begin p[w[tt,1]]:=1; t[tail]:=w[tt,1]; inc(tail); end;
end;
tt:=w[tt,3];
end;
p[v]:=0;
end;
end;
procedure tarjan(a:longint);
var tt:longint;
begin
inc(len); dfn[a]:=len; low[a]:=len; inc(t[0]); t[t[0]]:=a; p[a]:=1;
tt:=z[a,3];
while tt<>0 do
begin
if dfn[z[tt,1]]=0
then begin tarjan(z[tt,1]); low[a]:=min(low[z[tt,1]],low[a]); end
else if p[z[tt,1]]=1 then low[a]:=min(dfn[z[tt,1]],low[a]);
tt:=z[tt,3];
end;
if dfn[a]=low[a] then begin
inc(scc);
repeat
p[t[t[0]]]:=0;
id[t[t[0]]]:=scc;
dec(t[0]);
until a=t[t[0]+1];
end;
end;
begin
while not eof do
begin
readln(n,m); len:=n+1; if (n=0)and(m=0) then break;
for i:=1 to m do
begin readln(a,b,c); initz(a,b,c); end;
z[0,1]:=len; len:=0; scc:=0; t[0]:=0;
for i:=1 to n do
if dfn[i]=0 then tarjan(i);
len:=scc+1;
for i:=1 to n do
begin
tt:=z[i,3];
while tt<>0 do
begin
if id[i]<>id[z[tt,1]] then initw(id[i],id[z[tt,1]],z[tt,2]);
tt:=z[tt,3];
end;
end;
readln(q);
for i:=1 to q do
begin readln(a,b); x[i,1]:=id[a]; x[i,2]:=id[b]; x[i,3]:=i; end;
sort(1,q,1); {x[i,1]}
x[0,1]:=0;
for i:=1 to q do
begin
if x[i,1]<>x[i-1,1] then spfa(x[i,1]);
x[i,4]:=dist[x[i,2]];
end;
sort(1,q,3); {x[i,3]}
for i:=1 to q do
if x[i,4]=1000000
then writeln('Nao e possivel entregar a carta')
else writeln(x[i,4]);
writeln;
for i:=1 to n do
for j:=1 to 3 do
w[i,j]:=0;
for i:=1 to n do
for j:=1 to 3 do
z[i,j]:=0;
for i:=1 to n do
begin dfn[i]:=0; low[i]:=0; end;
end;
end.