bzoj 2152 点剖分
比较裸的点剖分,访问到每个重心时,记录一个b数组,
代表当前子树中长度为i的边的数量是b[i],因为是3的倍数,
所以边长mod 3保存就行了,然后记录一个sum数组,代表
当前子树中一个子节点为根的子树中的情况(类似b),然后
用这两个数组不断的更新答案就行了。
/************************************************************** Problem: 2152 User: BLADEVIL Language: Pascal Result: Accepted Time:572 ms Memory:1360 kb ****************************************************************/ //By BLADEVIL var n :longint; pre, other, len :array[0..40010] of longint; last :array[0..20010] of longint; l, top :longint; size, stack, yy :array[0..20010] of longint; ff :array[0..40010] of boolean; root :longint; b, sum :array[0..10] of longint; ans :longint; function gcd(x,y:longint):longint; begin if x<y then exit(gcd(y,x)) else if y=0 then exit(x) else exit(gcd(y,x mod y)); end; procedure connect(x,y,z:longint); begin inc(l); pre[l]:=last[x]; last[x]:=l; other[l]:=y; len[l]:=z; end; procedure dfs_size(x,fa:longint); var q, p :longint; begin size[x]:=1; inc(top); stack[top]:=x; q:=last[x]; while q<>0 do begin p:=other[q]; if (ff[q]) or (p=fa) then begin q:=pre[q]; continue; end; dfs_size(p,x); inc(size[x],size[p]); q:=pre[q]; end; yy[x]:=fa; end; procedure getroot(u:longint); var ms, s, x, p, q :longint; i :longint; begin top:=0; dfs_size(u,0); ms:=maxlongint; for i:=1 to top do begin x:=stack[i]; s:=size[u]-size[x]; q:=last[x]; while q<>0 do begin p:=other[q]; if (ff[q]) or (p=yy[x]) then begin q:=pre[q]; continue; end; if size[p]>s then s:=size[p]; q:=pre[q]; end; if s<ms then begin ms:=s; root:=x; end; end; end; procedure dfs_value(x,fa,lz:longint); var q, p :longint; begin inc(sum[lz mod 3]); q:=last[x]; while q<>0 do begin p:=other[q]; if (p=fa) or (ff[q]) then begin q:=pre[q]; continue; end; dfs_value(p,x,lz+len[q]); q:=pre[q]; end; end; procedure solve(u:longint); var i, q, p :longint; begin getroot(u); if top=1 then exit; fillchar(b,sizeof(b),0); b[3]:=1; top:=0; q:=last[root]; while q<>0 do begin p:=other[q]; if ff[q] then begin q:=pre[q]; continue; end; fillchar(sum,sizeof(sum),0); dfs_value(p,root,len[q]); for i:=0 to 3 do ans:=ans+b[i]*sum[3-i]; ans:=ans+sum[0]*b[0]; for i:=0 to 3 do inc(b[i],sum[i]); q:=pre[q]; end; q:=last[root]; while q<>0 do begin p:=other[q]; if ff[q] then begin q:=pre[q]; continue; end; ff[q]:=true; ff[q xor 1]:=true; solve(p); q:=pre[q]; end; end; procedure main; var i :longint; x, y, z :longint; ans1, ans2 :longint; g :longint; begin read(n); l:=1; fillchar(b,sizeof(b),$ff); b[0]:=0; for i:=1 to n-1 do begin read(x,y,z); z:=z mod 3; connect(x,y,z); connect(y,x,z); end; ans:=0; solve(1); ans1:=2*ans+n; ans2:=n*n; g:=gcd(ans1,ans2); writeln(ans1 div g,'/',ans2 div g); end; begin main; end.