HDU 4275 Color the Tree(树同构)
2012-09-22 10:47
309 查看
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4275
题意:给出一个n个节点的树,有m种颜色。问不同的染色方案有多少?
思路:本题首先要解决的就是对称的情况怎么办,网上说要找到树的中心,也就是找到树上的一条最长路,最长路为奇数,则中间一个节点作为根节点,否则,在中间增加一个节点作为根节点使得两边的最长路相等。然后就是树形DP,ans[u]表示以u为根节点的子树的总的染色方案,hash[u]存储以u为根节点的子树的结构。设u节点有k个子节点,v1,v2……vk,首先将子节点按照hash值排序,这样,同构的子树在排序后就会相邻,设有x个子树同构,则这x个子树总的染色方案为C(ans[v]+x-1,x)。这个式子是怎么推出来的我也不清楚,反正试了个ans[v]=2,x=2的是对的。接着就是将这些相乘就得到u节点的ans值,u节点的hash值由子节点的hash值Hash得到。
题意:给出一个n个节点的树,有m种颜色。问不同的染色方案有多少?
思路:本题首先要解决的就是对称的情况怎么办,网上说要找到树的中心,也就是找到树上的一条最长路,最长路为奇数,则中间一个节点作为根节点,否则,在中间增加一个节点作为根节点使得两边的最长路相等。然后就是树形DP,ans[u]表示以u为根节点的子树的总的染色方案,hash[u]存储以u为根节点的子树的结构。设u节点有k个子节点,v1,v2……vk,首先将子节点按照hash值排序,这样,同构的子树在排序后就会相邻,设有x个子树同构,则这x个子树总的染色方案为C(ans[v]+x-1,x)。这个式子是怎么推出来的我也不清楚,反正试了个ans[v]=2,x=2的是对的。接着就是将这些相乘就得到u节点的ans值,u节点的hash值由子节点的hash值Hash得到。
#include <iostream> #include <algorithm> #include <cstdio> #include <cstring> using namespace std; struct node { int v,next; }; struct Node { __int64 hash,ans; }; const __int64 mod=1000000007; const __int64 P=10003; const __int64 Q=100000037; node edges[200005]; Node q[50005]; int head[50005],e,E,M,MM,C,f[50005],dp[50005],n; __int64 hash[100005],ans[100005],p[100005],son[50005]; void Add(int u,int v) { edges[e].v=v; edges[e].next=head[u]; head[u]=e++; } __int64 POW(__int64 a,__int64 b) { __int64 ans=1; while(b) { if(b&1) ans=(ans*a)%mod; a=(a*a)%mod; b>>=1; } return ans; } __int64 cal(int n,int m) { if(n==m) return 1; __int64 n1=1,n2=p[m],i; for(i=1;i<=m;i++) n1=n1*(n-i+1)%mod; return n1*POW(n2,mod-2)%mod; } int cmp(Node a,Node b) { return a.hash<b.hash; } void init() { int i; p[1]=1; for(i=2;i<=100000;i++) p[i]=p[i-1]*i%mod; } int DFS(int u,int pre) { int m1=0,m2=0,i,v,t; for(i=head[u];i!=-1;i=edges[i].next) { v=edges[i].v; if(v==pre) continue; t=DFS(v,u); if(t>m1) m2=m1,m1=t,f[u]=i; else if(t>m2) m2=t; } if(M<m1+m2) MM=u,M=m1+m2; dp[u]=m1; return dp[u]+1; } void DFS1(int u,int pre) { int i,j,v; son[u]=0; for(i=head[u];i!=-1;i=edges[i].next) { v=edges[i].v; if(v==pre||i==E||i==(E^1)) continue; ans[v]=C; DFS1(v,u); son[u]++; } if(!son[u]) { hash[u]=1; return; } for(j=0,i=head[u];i!=-1;i=edges[i].next) { v=edges[i].v; if(v==pre||i==E||i==(E^1)) continue; q[j].hash=hash[v]; q[j++].ans=ans[v]; } sort(q,q+son[u],cmp); hash[u]=977872; for(i=0;i<son[u];i++) { for(j=i;j<son[u]&&q[i].hash==q[j].hash;j++) { hash[u]*=P; hash[u]^=q[j].hash; hash[u]%=mod; } j--; ans[u]*=cal(q[i].ans+j-i,j-i+1); ans[u]%=mod; i=j; } } int main() { init(); while(scanf("%d%d",&n,&C)!=-1) { memset(head,-1,sizeof(head)); e=2; int i,u,v; for(i=1;i<n;i++) { scanf("%d%d",&u,&v); Add(u,v); Add(v,u); } M=-1;DFS(1,-1); if(M&1) { while(dp[MM]*2>M+1) MM=edges[f[MM]].v; E=f[MM]; Add(MM,n+1); Add(n+1,MM); Add(edges[f[MM]].v,n+1); Add(n+1,edges[f[MM]].v); MM=n+1; ans[MM]=1; } else { E=0; while(dp[MM]*2>M) MM=edges[f[MM]].v; ans[MM]=C; } DFS1(MM,-1); printf("%I64d\n",ans[MM]); } return 0; }
相关文章推荐
- HDU 4275 Color the Tree(哈希+树同构+组合数学+树形dp)
- HDU 4275 Color the Tree 树的Hash 2012年长春网络赛I题
- HDU 4275 Color the Tree 树的不重复染色 求树的中心+hash
- hdu 4603 Color the Tree
- hdu 4603 Color the Tree
- hdu 4603 Color the Tree
- 多效第16场 HDU 3999 The order of a Tree(二叉树)
- HDU 1556 Color the ball
- HDU 3999 The order of a Tree 二叉搜索树 BST
- HDU 4718 The LCIS on the Tree (树链剖分+线段树区间合并)
- hdu 1556 Color the ball(修改区间)
- 【HDU】 1166 Color the ball
- hdu 3999 The order of a Tree
- HDU 1556 Color the ball
- hdu 1199 Color the Ball (线段树区间合并,离散化)
- HDU 1566 Color the ball
- hdu-1556-Color the ball(树状数组)
- HDU 1556 - Color the ball
- HDU 1199 Color the Ball(线段切割 离散化思想)
- hdu 1556 Color the ball (线段树+代码详解)