良好应用:2013noip提高组day1压轴题货车运输
思路:可以明显看出是最大生成树,然后可以想到寻找路径,结果就是路径上的最小值(因为是树,所以路径是唯一的!)
最后就是如何求路径最小值了,可以先求出lca,同时预处理,完美地解决。
参考网址:程序写得很漂亮
参考程序(一遍过):
var
v:array[0..111000]of boolean;
dp,mm:array[0..110000,0..20]of longint;
a,b,c,f,head,depth:array[0..110000]of longint;
e:array[0..110000]of record
j,w,next:longint;
end;
cnt,n,m:longint;
procedure openfile;
begin
assign(input,'truck.in');reset(input);
assign(output,'truck.out');rewrite(output);
end;
procedure closfile;
begin
close(input);close(output);
end;
function min(a,b:longint):longint;
begin
if a<b then exit(a);
exit(b);
end;
procedure init;
var
i:longint;
begin
readln(n,m);
for i:=1 to n do f[i]:=i;
for i:=1 to m do readln(a[i],b[i],c[i]);
end;
procedure kp(l,r:longint);
var
i,j,x,t:longint;
begin
i:=l;j:=r;x:=c[l+random(r-l+1)];
repeat
while c[i]>x do i:=i+1;
while c[j]<x do j:=j-1;
if i<=j then
begin
t:=c[i];c[i]:=c[j];c[j]:=t;
t:=a[i];a[i]:=a[j];a[j]:=t;
t:=b[i];b[i]:=b[j];b[j]:=t;
i:=i+1;j:=j-1;
end;
until i>j;
if i<r then kp(i,r);
if j>l then kp(l,j);
end;
{procedure newcode(u,v,i:longint);
begin
cnt:=cnt+1;
e[cnt].cap:=c[i];
e[cnt].u:=a[i];
e[cnt].v:=b[i];
end;}
procedure insert(u,v,c:longint);
begin
cnt:=cnt+1;
e[cnt].j:=v;e[cnt].w:=c;e[cnt].next:=head[u];head[u]:=cnt;
cnt:=cnt+1;
e[cnt].j:=u;e[cnt].w:=c;e[cnt].next:=head[v];head[v]:=cnt;
end;
function find(x:longint):longint;
begin
if f[x]<>x then f[x]:=find(f[x]);
exit(f[x]);
end;
procedure kruskal;
var
i,count,p,q:Longint;
begin
count:=0;
for i:=1 to m do
begin
p:=find(a[i]);q:=find(b[i]);
if p<>q then
begin
//newcode(a[i],b[i],i);
//newcode(b[i],a[i],i);
insert(a[i],b[i],c[i]);
insert(b[i],a[i],c[i]);
f[q]:=p;
count:=count+1;
if count=n-1 then break;
end;
end;
for i:=1 to n do f[i]:=find(i);
end;
procedure dfs(x,i:longint);
var
j,k:longint;
begin
v[x]:=true;depth[x]:=i;
j:=head[x];
while j>0 do
begin
if not v[e[j].j] then
begin
dp[e[j].j,0]:=x;mm[e[j].j,0]:=e[j].w;k:=0;
while dp[dp[e[j].j,k],k]<>0 do
begin
dp[e[j].j,k+1]:=dp[dp[e[j].j,k],k];
mm[e[j].j,k+1]:=min(mm[e[j].j,k],mm[dp[e[j].j,k],k]);
k:=k+1;
end;
dfs(e[j].j,i+1);
end;
j:=e[j].next;
end;
end;
procedure lca;
var
i:longint;
begin
for i:=1 to n do
if not v[i] then dfs(i,0);
end;
procedure prepare;
begin
randomize;
kp(1,m);
kruskal;
lca;
end;
function answer(x,y:longint):longint;
var
t,ans,k:longint;
begin
if depth[x]<depth[y] then
begin
t:=x;x:=y;y:=t;
end;
ans:=maxlongint;t:=depth[x]-depth[y];k:=0;
while t<>0 do
begin
if t and 1=1 then
begin
ans:=min(ans,mm[x,k]);
x:=dp[x,k];
end;
t:=t shr 1;
k:=k+1;
end;
k:=0;
while x<>y do
begin
if (dp[x,k]<>dp[y,k])or(k=0) then
begin
ans:=min(ans,min(mm[x,k],mm[y,k]));
x:=dp[x,k];y:=dp[y,k];
k:=k+1;
end
else k:=k-1;
end;
exit(ans);
end;
procedure solve;
var
q,from,tt:longint;
begin
readln(q);
for q:=1 to q do
begin
readln(from,tt);
if f[from]<>f[tt] then writeln(-1)
else writeln(answer(from,tt));
end;
end;
procedure main;
begin
openfile;
init;
prepare;
solve;
closfile;
end;
begin
main;
end.