题意:一棵n个节点的树,找到一个点到其他节点容量和最大,两点之间的容量为路径上的最小边
经过简单的画图,发现可以用并查集..把答案节点维护成并查集的根节点
解决两点的容量问题,因为是最小边,我们排序后从大到小枚举,这样我们所处理的边一定是端点a、b之间最短路,可以直接贡献答案
对于a、b所在集合的根节点ta、tb
sum[ta]=sum[ta]+len*size[tb]
sum[tb]=sum[tb]+len*size[ta]
其中size[x]表示根节点是x的节点数
然后并查集合并,因为我们把答案节点维护成并查集的根节点,所以必须把sum小的往sum大的合并,即保证根节点的sum是该点集中最大的。更新ans
type
rec=record
a,b,len:longint;
end;
var
n :longint;
i :longint;
ans :int64;
f,size :array[0..200010] of longint;
sum :array[0..200010] of int64;
l :array[0..200010] of rec;
function max(a,b:int64):int64;
begin
if a<b then exit(b) else exit(a);
end;
function get_Father(x:longint):longint;
begin
if x=f[x] then exit(x);
f[x]:=get_father(f[x]);
exit(f[x]);
end;
procedure sort(ll,rr:longint);
var
x,i,j:longint;
y:rec;
begin
i:=ll; j:=rr; x:=l[(ll+rr) div 2].len;
while (i<=j) do
begin
while l[i].len<x do inc(i);
while l[j].len>x do dec(j);
if (i<=j) then
begin
y:=l[i]; l[i]:=l[j]; l[j]:=y;
inc(i); dec(j);
end;
end;
if i<rr then sort(i,rr);
if j>ll then sort(ll,j);
end;
procedure work;
var
ta,tb,c:longint;
t1,t2,t3:int64;
begin
for i:=n-1 downto 1 do
begin
ta:=get_father(l[i].a);
tb:=get_father(l[i].b);
t1:=sum[ta]+int64(l[i].len)*int64(size[tb]);
t2:=sum[tb]+int64(l[i].len)*int64(size[ta]);
if t1<t2 then
begin
c:=ta; ta:=tb; tb:=c;
t3:=t1; t1:=t2; t2:=t3;
end;
f[tb]:=ta;
sum[ta]:=t1;
inc(size[ta],size[tb]);
ans:=t1;
end;
end;
begin
while not eof do
begin
read(n);ans:=0;
for i:=1 to n do f[i]:=i;
for i:=1 to n do size[i]:=1;
fillchar(sum,sizeof(sum),0);
for i:=1 to n-1 do read(l[i].a,l[i].b,l[i].len);
sort(1,n-1);
work;
writeln(ans);
readln;
end;
end.
——by Eirlys