标签:target include a long and wan 条件 ext cto height
题目链接:http://acm.hdu.edu.cn/showproblem.php?
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
题意:
一颗树共同拥有 n 个节点,现要把他们从 1 - n 编号。
条件:
1、每一个节点的子节点之间号是连续的(如:4 5 6 或者6 5 4均可)!
2、每棵子树的编号自身是连续的!
求一共同拥有多少种可能的编号方式。
PS:
假设一个节点的子树中规模大于1的子树多于2个。那么肯定是不可能有满足要求的安排编号的!
在一个区间中。规模大于1的子树必定选择的是最左边或者最右边的连续的编号。
剩下规模为1的子树,有N!种安排方法。
手动扩栈,须要用C++提交!
代码例如以下:
#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
#define LL long long
#define maxn 100017
const LL mod = 1e9+7;
vector<int> v[maxn];
LL f[maxn];
LL son[maxn];
void init()
{
f[0] = 1;
for(int i = 1; i <= maxn; i++)
{
f[i] = (i*f[i-1])%mod;
}
}
LL dfs(int u, int father)
{
son[u] = 1;
int x = 0, y = 0;
LL ans = 1;
int num = v[u].size();
for(int i = 0; i < num; i++)
{
if(v[u][i] == father)
{
continue;
}
int t1 = v[u][i];
LL tt = dfs(t1, u);
ans = (ans*tt)%mod;
if(son[v[u][i]] >= 2)//规模大于1的子树
{
x++;
}
else
{
y++;
}
if(ans==0 || x > 2)//ans==0无解,规模大于1的子树多于2个肯定不可能
{
return 0;
}
son[u]+=son[v[u][i]];
}
if(x)
{
ans*=2;
ans%=mod;
}
ans = (ans*f[y])%mod;
return ans;
}
int main()
{
int t;
int n;
int cas = 0;
init();
scanf("%d",&t);
while(t--)
{
memset(son,0,sizeof(son));
scanf("%d",&n);
for(int i = 0; i < maxn; i++)
{
v[i].clear();
}
int x, y;
for(int i = 1; i < n; i++)
{
scanf("%d%d",&x,&y);
v[x].push_back(y);
v[y].push_back(x);
}
LL ans = dfs(1, -1);
if(son[1] > 1)
{
ans*=2;
ans%=mod;
}
printf("Case #%d: %I64d\n",++cas,ans);
}
return 0;
}
标签:target include a long and wan 条件 ext cto height
原文地址:http://www.cnblogs.com/clnchanpin/p/6790348.html