luogu2634 聪聪可可 (树形dp)

要求出两点间距离==0(mod3) 的数量,然后除以(n*n)

设f[i][j]为i的子树到i的距离==j(mod3)的数量,然后做树形dp即可

因为要最简,所以要求一下gcd,然后除下去

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<cstring>
 4 using namespace std;
 5 const int maxn=20020;
 6 
 7 int rd(){
 8     int x=0;char c=getchar();
 9     while(c<'0'||c>'9') c=getchar();
10     while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
11     return x;
12 }
13 
14 
15 struct Edge{
16     int b,l,ne;
17 }eg[maxn*2],son[maxn];
18 int N;
19 int f[maxn][3],f2[maxn][3],egh[maxn],sonh[maxn],ect,sct;
20 int ansp;
21 
22 inline void adeg(int a,int b,int c){
23     eg[ect].b=b;eg[ect].l=c;eg[ect].ne=egh[a];egh[a]=ect++;
24 }
25 
26 void build(int x,int fa){
27     for(int i=egh[x];i!=-1;i=eg[i].ne){
28         int b=eg[i].b;if(b==fa) continue;
29         son[sct].b=b;son[sct].l=eg[i].l;son[sct].ne=sonh[x];sonh[x]=sct++;
30         build(b,x);
31     }
32 }
33 
34 void dfs(int x){
35     f[x][0]=1;
36     for(int i=sonh[x];i!=-1;i=son[i].ne) dfs(son[i].b);
37     for(int i=sonh[x];i!=-1;i=son[i].ne){
38         int b=son[i].b,l=son[i].l;
39         for(int j=0;j<=2;j++) f[x][(j+l)%3]+=f[b][j],f2[b][(j+l)%3]=f[b][j];
40     }ansp+=f[x][0];
41     for(int i=sonh[x];i!=-1;i=son[i].ne){
42         int b=son[i].b,l=son[i].l;
43         for(int j=0;j<=2;j++) ansp+=f2[b][(3-j%3)%3]*(f[x][j]-f2[b][j]);
44     }
45 }
46 
47 int gcd(int a,int b){
48     if(!b) return a;
49     else return gcd(b,a%b);
50 }
51 
52 int main(){
53     int i,j,k;
54     N=rd();
55     memset(egh,-1,sizeof(egh));memset(sonh,-1,sizeof(sonh));
56     for(i=1;i<N;i++){
57         int a=rd(),b=rd(),c=rd();
58         adeg(a,b,c);adeg(b,a,c);
59     }build(1,0);dfs(1);
60     i=gcd(ansp,N*N);
61     printf("%d/%d\n",ansp/i,N*N/i);
62 } 

 

posted @ 2018-09-14 21:20  Ressed  阅读(156)  评论(0编辑  收藏  举报