为了 随时 与 rainbow快速交流, Freda制造了 两部传呼机 。Freda和 rainbow所在的地方有N座房屋、M条双向 光缆 。每条光缆连接两座房屋, 传呼机发出的信号只能沿着光缆传递,并且 传呼机的信号 从光缆的其中一端传递到另需要花费 t单位时间 。现在 Freda要 进行 Q次试验, 每次选取两座房屋,并想知道 传呼机的信号在这两座房屋之间传递 至少需 要多长时间。 Freda 和 rainbow简直弱爆了有木有 ,请你帮他们吧……
N座房屋 通过光缆 一定是连通的, 并且这 M条光缆有以下三类连接情况:
A:光缆不形成环 ,也就是光缆仅 有 N-1条。
B:光缆只 形成一个环,也就是光缆 仅有 N条。
C:每条光缆仅在一个环中。
Input
第一行 包含三个用空格隔开的整数, N、M和 Q。
接下来 M行每三个整数 x、y、t,表示 房屋 x和 y之间有一条传递时为 t的光缆 。
最后 Q行每两个整数 x、y,表示 Freda想知道 在 x和 y之间传呼最少需要多长时间。
Output
输出 Q行,每一个整数表示 Freda每次试验的结果 。
A类直接LCA
B类考虑两种情况: 去掉一条边成树的情况,然后再加上那条边,求到那条边两个端点的距离再加上那条边的长度,取 MIN 。
C类:传说中的业界毒瘤仙人掌图。
可以先去环。
考虑一个这样的图:
要求5到3之间最短路径。
可以为每个环规定一个环顶,然后将环内其他顶点向环顶连边。这条边的权值就是该点到环顶的最小距离。
这个可以一边dfs求出环的总长度,然后将环长度减去一条路径的长度就是另一条路径的长度了。
因为在同一个环之前的最小路径唯一,所以直接lca就可以了。
先把5上升到与3的lca下的第一层,然后看他们是否在同一环内。如果是的话,就求环内最小距离+lca,如果不是的话就直接原lca长度+两条连往lca的边即可即可。
环内最小距离如何求?
记录一下两点走两条路径到环顶的距离的距离。然后就可以愉快的分类讨论:经过环顶,不经过环顶了。
var
hh,hu,pr,su,tw,w,tnext,next,e,te:array[-60000..60000] of longint;
len,dst,s,deep,father,thead,head:array[0..10000] of longint;
vis:array[1..10000] of boolean;
f,g:array[0..10000,0..14] of longint;
rt,i,ru,l,r,k,ttot,tot,n,m,q,j,x,y,t,ht:longint;
procedure new(a,b,t:longint);
begin
inc(tot);
e[tot]:=b; w[tot]:=t;
next[tot]:=head[a];
head[a]:=tot;
e[tot+m]:=a; w[tot+m]:=t;
next[tot+m]:=head[b];
head[b]:=tot+m;
end;
procedure tnew(a,b,t:longint);
begin
inc(ttot);
te[ttot]:=b; tw[ttot]:=t;
tnext[ttot]:=thead[a];
thead[a]:=ttot;
te[ttot+m]:=a; tw[ttot+m]:=t;
tnext[ttot+m]:=thead[b];
thead[b]:=ttot+m;
end;
function min(a,b:longint):longint;
begin
if a>b then exit(b) else exit(a);
end;
procedure swap(var a,b:longint);
var t:longint;
begin
t:=a; a:=b; b:=t;
end;
function lca(x,y:longint):longint;
var i:longint;
begin
lca:=0;
if deep[x]<deep[y] then swap(x,y);
for i:=14 downto 0 do
if deep[g[x,i]]>deep[y] then
begin
inc(lca,f[x,i]);
x:=g[x,i];
end;
if deep[x]<>deep[y] then
begin
inc(lca,f[x,0]);
x:=g[x,0];
end;
if x=y then exit(lca);
for i:=14 downto 0 do
if g[x,i]<>g[y,i] then
begin
inc(lca,f[x,i]+f[y,i]);
x:=g[x,i]; y:=g[y,i];
end;
if (hh[x]=hh[y])and(hh[x]+hh[y]<>0)and(m>n-1) then
begin
exit(lca+min(abs(pr[x]-pr[y]),min(pr[x]+su[y],pr[y]+su[x])));
end else exit(lca+f[x,0]+f[y,0]);
end;
procedure init_lca(x:longint);
begin
for i:=1 to 14 do
begin
g[x,i]:=g[g[x,i-1],i-1];
f[x,i]:=f[g[x,i-1],i-1]+f[x,i-1];
end;
end;
procedure circle(x,fa,way,lastpath:longint);
var i,k:longint;
begin
inc(s[0]); s[s[0]]:=x;
dst[x]:=way;
vis[x]:=true;
k:=head[x];
while (k<>0) do
begin
if vis[e[k]]=false then
circle(e[k],x,way+w[k],k)
else
if (hu[k]=0)and(k<>lastpath+m)and(k<>lastpath-m) then
begin
hu[k]:=1; hu[k-m]:=1; hu[k+m]:=1;
i:=s[0];
len[e[k]]:=dst[x]-dst[e[k]]+w[k];
inc(ht);
while s[i]<>e[k] do
begin
hh[s[i]]:=ht;
father[s[i]]:=e[k];
pr[s[i]]:=dst[s[i]]-dst[e[k]];
su[s[i]]:=len[e[k]]-(dst[s[i]]-dst[e[k]]);
tnew(e[k],s[i],min(dst[s[i]]-dst[e[k]],
len[e[k]]-(dst[s[i]]-dst[e[k]])));
dec(i);
end;
end;
k:=next[k];
end;
if (hh[x]=0)and(fa<>0) then
begin
tnew(fa,x,w[lastpath]);
end;
dec(s[0]);
end;
procedure dfs(x,way,dep,fa:longint);
var
k:longint;
begin
dst[x]:=way;
deep[x]:=dep;
init_lca(x);
k:=thead[x];
while k<>0 do
begin
if te[k]<>fa then
begin
f[te[k],0]:=tw[k];
g[te[k],0]:=x;
dfs(te[k],way+tw[k],dep+1,x);
end;
k:=tnext[k];
end;
end;
procedure init;
begin
deep[0]:=-maxlongint;
readln(n,m,q);
for i:=1 to m do
begin
readln(x,y,t);
new(x,y,t);
end;
if m>n-1 then circle(1,0,0,0) else
begin
tw:=w;
thead:=head;
tnext:=next;
te:=e;
ttot:=tot;
end;
dfs(1,0,1,0);
end;
begin
init();
for i:=1 to q do
begin
readln(x,y);
writeln(lca(x,y));
end;
end.