bzoj2152: 聪聪可可

树形dp。

本来是想做一系列树分治的,结果这道题树形dp就可以了(膜popoqqq大神)

f数组保存每个节点距离为0,1,2的点对数量。

不断统计就可以辣。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn = 20000 + 10;
const int maxm = 40000 + 10;

struct data {
    int a,b,c;
        
    void rotate() {
        swap(a,b);    
        swap(a,c);
    }
    
    data operator += (const data rhs) {
        a+=rhs.a;
        b+=rhs.b;
        c+=rhs.c;
    }
    
    data() {a=1;b=0;c=0;}    
}f[maxn];
int n,res;
int g[maxn],v[maxm],next[maxm],c[maxm],eid;

void addedge(int a,int b,int C) {
    v[eid]=b; c[eid]=C; next[eid]=g[a]; g[a]=eid++;
    v[eid]=a; c[eid]=C; next[eid]=g[b]; g[b]=eid++;
}

void update(data x,data y) {
    res+=x.a*y.a;
    res+=x.b*y.c;
    res+=x.c*y.b;
}

void dfs(int u,int from) {
    for(int i=g[u];~i;i=next[i]) if(v[i]!=from) {
        dfs(v[i],u);
        for(int j=c[i];j;j--) f[v[i]].rotate();    
        update(f[u],f[v[i]]);
        f[u]+=f[v[i]];
    }
}

int gcd(int a,int b) {
    return b==0?a:gcd(b,a%b);
}    

int main() {
    memset(g,-1,sizeof(g));
    scanf("%d",&n);
    for(int i=1,u,v,w;i<n;i++) {
        scanf("%d%d%d",&u,&v,&w);
        addedge(u,v,w%3);
    }
    dfs(1,0);
    res=res*2+n;
    int d=gcd(res,n*n);
    printf("%d/%d\n",res/d,n*n/d);
    return 0;
}

posted @ 2016-07-09 00:19  invoid  阅读(109)  评论(0编辑  收藏  举报