uva 1664 並查集+貪心
阿新 • • 發佈:2019-01-26
題意:一棵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
——by Eirlystype 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.