4
1 2 1
1 3 2
3 4 3
2
2 2
3
一看这道题,一定要用数组模拟链表啦~,因为n=50000,用领接表的话空间早就爆了……
体型:贪心+二分+树
我们可以构造一棵树,然后让全部的军队在时间允许之下(设当前时间为mid)尽量向父亲节点跑,跑到首都为止。如果他不够时间再跑回从那个点跑到首都的那个点,则就将这个军队停留在这个点。证明过程到时候写。
这时我们将能留在首都的点、剩余没有分配军队的深度为1的点与首都的边的权值从小到大排个序,再一对一匹配。如果不成功,则看看下一个留在首都的点能不能与当前这条边匹配。如果还剩下有没有匹配到的边,则证明答案比mid大。
最后输出l就可以了。
var next,head,num,deep,b,go,f,g,h1,h2:array[0..100001] of int64;
fa,d,d1:array[0..50001,1..2] of int64;
c,e,e1:array[0..50001,1..3] of int64;
a,h,g1,g2:array[0..50001] of boolean;
i,j,k,l,r,mid,n,m,t,s,xx,yy,x,y,tot,o,wz:longint;
ans,min:int64;
p:boolean;
procedure qsort(l,r:longint);
var i,j:longint;
t:array[1..3] of int64;
mid:int64;
begin
i:=l;
j:=r;
mid:=e1[(l+r)div 2,3];
repeat
while e1[i,3]<mid do inc(i);
while e1[j,3]>mid do dec(j);
if i<=j then
begin
t:=e1[i];
e1[i]:=e1[j];
e1[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if l<j then qsort(l,j);
if i<r then qsort(i,r);
end;
procedure q1(l,r:longint);
var i,j:longint;
t:array[1..2] of int64;
mid:int64;
begin
i:=l;
j:=r;
mid:=d1[(l+r)div 2,2];
repeat
while d1[i,2]<mid do inc(i);
while d1[j,2]>mid do dec(j);
if i<=j then
begin
t:=d1[i];
d1[i]:=d1[j];
d1[j]:=t;
inc(i);
dec(j);
end;
until i>j;
if l<j then q1(l,j);
if i<r then q1(i,r);
end;
function mi(a,b:int64):int64;
begin
if a<b then exit(a) else exit(b);
end;
function dg(k:longint):boolean;
var i:longint;
p1:boolean;
begin
dg:=false;
i:=next[k];
h[k]:=true;
if a[k] and (k<>1) then exit(true);
if g[k]<>1 then a[k]:=true;
while i>0 do
begin
if not h[go[i]] then
begin
p1:=dg(go[i]);
a[k]:=a[k] and p1;
end;
i:=head[i];
end;
end;
function dg1(x:int64):longint;
var i:longint;
p:longint;
begin
i:=next[x];
dg1:=h1[x];
h[x]:=true;
while i>0 do
begin
if not h[go[i]] then
begin
p:=dg1(go[i]);
h2[x]:=h2[x]+h2[go[i]];
end;
i:=head[i];
end;
end;
procedure lb(x,y,z:int64);
begin
inc(tot);
go[tot]:=y;
inc(g[y]);
head[tot]:=next[x];
next[x]:=tot;
num[tot]:=z;
end;
procedure bs(x,y:int64);
var i:longint;
begin
i:=next[x];
deep[x]:=y;
while i>0 do
begin
if (deep[go[i]]=0)and(go[i]<>1) then
begin
bs(go[i],y+1);
fa[go[i],1]:=x;
fa[go[i],2]:=num[i];
end;
i:=head[i];
end;
end;
function get(n:longint):longint;
begin
if f[n]=0 then exit(n)
else
begin
f[n]:=get(f[n]);
get:=f[n];
end;
end;
function lca(x,y:int64):int64;
var ans:int64;
begin
ans:=0;
while (deep[x]>deep[y]) do
begin
ans:=ans+fa[x,2];
x:=fa[x,1];
end;
while (deep[y]>deep[x]) do
begin
ans:=ans+fa[y,2];
y:=fa[y,1];
end;
if x=y then exit(ans);
while x<>y do
begin
ans:=ans+fa[x,2];
x:=fa[x,1];
ans:=ans+fa[y,2];
y:=fa[y,1];
end;
exit(ans);
end;
begin
readln(n);
for i:=1 to n-1 do
begin
read(c[i,1],c[i,2],c[i,3]);
if c[i,1]=1 then
begin
inc(d[0,1]);
d[d[0,1],1]:=c[i,2];
d[d[0,1],2]:=c[i,3];
end else
if c[i,2]=1 then
begin
inc(d[0,1]);
d[d[0,1],1]:=c[i,1];
d[d[0,1],2]:=c[i,3];
end;
end;
for i:=1 to n do
begin
x:=get(c[i,1]);
y:=get(c[i,2]);
if x<>y then
begin
f[x]:=y;
lb(c[i,1],c[i,2],c[i,3]);
lb(c[i,2],c[i,1],c[i,3]);
end;
end;
bs(1,0);
readln(m);
for i:=1 to m do
begin
read(b[i]);
inc(h1[b[i]]);
end;
h2:=h1;
dg1(1);
if m<d[0,1] then
begin
writeln(-1);
halt;
end;
l:=0;
r:=1000000000;
deep[0]:=0;
while l<r do
begin
mid:=(l+r)div 2;
fillchar(e1,sizeof(e1),0);
fillchar(d1,sizeof(d1),0);
fillchar(a,sizeof(a),0);
fillchar(e,sizeof(e),0);
fillchar(h,sizeof(h),0);
fillchar(g1,sizeof(g1),0);
fillchar(g2,sizeof(g2),0);
for i:=1 to m do
begin
x:=b[i];
ans:=0;
while deep[x]>0 do
begin
if (deep[x]=1) then
if ans+fa[x,2]<=mid then e[i,2]:=x;
ans:=ans+fa[x,2];
if ans>mid then break;
x:=fa[x,1];
end;
e[i,1]:=x;
e[i,3]:=mid-ans;
a[x]:=true;
if e[i,3]>=fa[e[i,2],2] then
begin
g1[i]:=true;
inc(e1[0,1]);
e1[e1[0,1]]:=e[i];
end else
if e[i,2]<>0 then
begin
a[e[i,2]]:=true;
g2[i]:=true;
end;
end;
a[1]:=dg(1);
for i:=1 to d[0,1] do
if not a[d[i,1]] then
begin
inc(d1[0,1]);
d1[d1[0,1]]:=d[i];
end;
for i:=1 to m do
if not g1[i] then
begin
if g2[i] and (h2[e[i,2]]>1) then
begin
inc(e1[0,1]);
e1[e1[0,1]]:=e[i];
end;
end;
q1(1,d1[0,1]);
qsort(1,e1[0,1]);
p:=false;
i:=1;
j:=0;
while (i<=d1[0,1]) do
begin
inc(j);
while (e1[j,3]<d1[i,2])and(j<=e1[0,1]+1) do inc(j);
if j>e1[0,1] then
begin
p:=true;
break;
end;
inc(i);
end;
if p then l:=mid+1 else r:=mid;
end;
writeln(l);
end.
这个标写的不是很好,希望各位大神能够雅正。
——2016.3.30 By Wzy