A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路。每一条道路对车辆都有重量限制,简称限重。现在有 q 辆货车在运输货物,司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物。
那么我们就先跑一个最大生成树对吧,然后找两点之间路径的最小值
找路径最小值什么的主要是用一个在线的LCA
在维护f数组同时我们再加入一个d数组,d[u,i]表示从u开始向上2^i步里的最小值
然后就可以了~
代码量什么的略大,我写了160行左右
const shuru='truck.in';
shuchu='truck.out';
maxlen=13;
type edge=record
from,too,wei:longint;
end;
var deep,father,headlist:array[0..10001] of longint;
next,weight,t:array[0..20001] of longint;
a:array[0..50001] of edge;
vis:array[0..10001] of boolean;
d,f:array[0..10001,0..13] of longint;
step,num,x,y,z,now,i,j,k,n,m,q:longint;
p:edge;
function min(a,b:longint):longint;
begin
if amid) do inc(i);
while (a[j].weij;
if j>l then qsort(l,j);
if ifather[step]) do step:=father[step];
while k<>step do
begin
x:=father[k];
father[k]:=step;
k:=x;
end;
exit(step);
end;
procedure merge(a,b:longint);
var fa1,fa2:longint;
begin
fa1:=find(a); fa2:=find(b);
father[fa2]:=fa1;
end;
procedure mit;
begin
qsort(1,m);
now:=1;
for i:=1 to n-1 do
begin
x:=a[now].from; y:=a[now].too; z:=a[now].wei;
while (find(x)=find(y)) do
begin
inc(now);
if now>=m+1 then break;
x:=a[now].from; y:=a[now].too; z:=a[now].wei;
end;
if now>=m+1 then break;
merge(x,y);
inc(num);
next[num]:=headlist[x];
headlist[x]:=num;
weight[num]:=z;
t[num]:=y;
inc(num);
next[num]:=headlist[y];
headlist[y]:=num;
weight[num]:=z;
t[num]:=x;
end;
end;
procedure dfs(u:longint);
var i:longint;
begin
for i:=1 to maxlen do f[u,i]:=f[f[u,i-1],i-1];
for i:=1 to maxlen do d[u,i]:=min(d[u,i-1],d[f[u,i-1],i-1]);
i:=headlist[u];
while i<>-1 do
begin
if (not(vis[t[i]])) then begin
i:=next[i];
continue;
end;
vis[t[i]]:=false;
f[t[i],0]:=u;
d[t[i],0]:=weight[i];
deep[t[i]]:=deep[u]+1;
dfs(t[i]);
i:=next[i];
end;
end;
function ask(a,b:longint):longint;
var i,del:longint;
begin
ask:=maxlongint;
if deep[a]>deep[b] then begin
step:=a;
a:=b;
b:=step;
end;
del:=deep[b]-deep[a];
for i:=0 to maxlen do if (del and (1 shl i))<>0 then begin
ask:=min(d[b,i],ask);
b:=f[b,i];
end;
if a<>b then begin
for i:=maxlen downto 0 do
if f[a,i]<>f[b,i] then begin
ask:=min(ask,d[b,i]);
ask:=min(ask,d[a,i]);
a:=f[a,i];
b:=f[b,i];
end;
ask:=min(ask,d[a,0]);
ask:=min(ask,d[b,0]);
end;
end;
procedure main;
begin
init;
mit;
fillchar(vis,sizeof(vis),true);
for i:=1 to n do
if vis[i] then begin
deep[i]:=1;
vis[i]:=false;
dfs(i);
end;
readln(q);
for i:=1 to q do
begin
readln(x,y);
if find(x)<>find(y) then writeln(-1)
else writeln(ask(x,y));
end;
close(input);
close(output);
end;
begin
main;
end.