标签:
http://acm.hdu.edu.cn/showproblem.php?pid=5379
2 9 2 1 3 1 4 3 5 3 6 2 7 4 8 7 9 3 8 2 1 3 1 4 3 5 1 6 4 7 5 8 4
Case #1: 32 Case #2: 16
/** hdu5379||2015多校联合第7场1011 树形统计 题目大意:给定一棵树n个节点,用1~n这n个数给每一个节点染色,兄弟节点染色值要连续,以当前节点为根节点的子树中所有节点的染色值要连续,问总共有 多少种染色的方案 解题思路:对于一个节点u: 1.如果他的兄弟节点中sum>=2的节点如果有两以上,则整棵树无解,输出0; 2.如果正好有2个那么二者可以分别在最左或最右,剩下的sum==1的节点全排列那么答案:2*A[son[fa[u]-2],如果fa[u]无兄弟节点那么fa[u]将在 以其为节点的子树中可以在最左或最右边,那么答案还要乘2,为:2*2*A[son[fa[u]-2]*dfs(son); 3.如果有1个,那么他自己可在两头答案:2*A[son[fa[u]-1]*dfs(son);,同样要考虑fa[u]无兄弟节点的情况 4.如果有0个,那么A[son[fa[u]]],同样要考虑fa[u]无兄弟节点的情况 值得一提的是:对于sum为1的节点的个数也要考虑,具体见代码注释 */ #pragma comment(linker, "/STACK:102400000,102400000") #include <stdio.h> #include <string.h> #include <algorithm> #include <iostream> using namespace std; typedef long long LL; const int maxn=100005; const LL mod=1e9+7; LL A[maxn]; int head[maxn],ip,n; int son[maxn],sum[maxn],bigson[maxn],fa[maxn]; ///儿子的数目,根节点为i的子树的节点树,子树节点数大于2的儿子个数,父亲节点 void init() { memset(head,-1,sizeof(head)); ip=0; } struct note { int v,next; } edge[maxn*2]; void addedge(int u,int v) { edge[ip].v=v,edge[ip].next=head[u],head[u]=ip++; } void dfs(int u,int pre)///对树的预处理,求出各种参数 { son[u]=0; bigson[u]=0; sum[u]=1; fa[u]=pre; for(int i=head[u]; i!=-1; i=edge[i].next) { int v=edge[i].v; if(v==pre)continue; dfs(v,u); son[u]++; if(sum[v]>1) { bigson[u]++; } sum[u]+=sum[v]; } //printf("sum%d:%d\n",u,sum[u]); // printf("son%d:%d\nbigson%d\n",u,son[u],bigson[u].size()); } LL dfs1(int u,int pre) { LL cnt=1; if(bigson[u]==1)///子树节点数大于1的儿子个数为1 { if(son[u]==1)///无兄弟节点此时在最左边和最右边属于同一种情况,无须乘2,下同 { cnt=(cnt*A[son[u]-1]%mod)%mod; } else { cnt=(cnt*A[son[u]-1]%mod*2)%mod; } if(son[fa[u]]==1)cnt=(cnt*2)%mod; } else if(bigson[u]==2)///子树节点数大于1的儿子个数为2 { cnt=(cnt*A[son[u]-2]%mod*2)%mod; if(son[fa[u]]==1)cnt=(cnt*2)%mod; } else if(bigson[u]>2)///子树节点数大于1的儿子个数大于2 { return 0; } else///无子树节点数大于1的儿子个数 { if(son[u]>0) { if(son[fa[u]]==1) return (2*A[sum[u]-1])%mod; return A[sum[u]-1]; } else if(son[u]==0) return 1; } for(int i=head[u]; i!=-1; i=edge[i].next)///递归进入儿子节点 { int v=edge[i].v; if(v==pre)continue; cnt=(cnt*dfs1(v,u))%mod; } // printf("dfs%d:%I64d\n",u,cnt); return cnt; } int main() { A[0]=1; for(int i=1; i<100005; i++) { A[i]=(A[i-1]*i)%mod; //printf("%I64d\n",A[i]); } int T,tt=0; scanf("%d",&T); while(T--) { scanf("%d",&n); init(); for(int i=1; i<=n-1; i++) { int u,v; scanf("%d%d",&u,&v); addedge(u,v); addedge(v,u); } son[0]=1; dfs(1,0); printf("Case #%d: %I64d\n",++tt,dfs1(1,0)); } return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。
标签:
原文地址:http://blog.csdn.net/lvshubao1314/article/details/47440783