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.

 

posted on 2014-01-08 08:28  BLADEVIL  阅读(375)  评论(0编辑  收藏  举报