标签: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