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