题目链接:
题目描述:
给出一个有n个节点的树,以节点1为根节点。问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号?
解题思路:
对于一个节点来讲,非叶子儿子节点最多有两个才能满足要求,否则满足子树节点连续的话就无法满足兄弟节点连续。然后有dfs计算每棵子树的贡献值,每棵子树的子节点可以分为叶子节点X和非叶子节点Y,叶子节点可以分配到一组连续的编号,非叶子节点只能分配到兄弟节点中最大或者最小编号两种情况,叶子节点的贡献值为X!。然后dfs跑一下就ok咯。
1 #include <queue> 2 #include <cstdio> 3 #include <cstring> 4 #include <iostream> 5 #include <algorithm> 6 #pragma comment (linker, "/STACK:1024000000,1024000000") 7 using namespace std; 8 9 const int maxn = 100005; 10 const int mod = (1e9 + 7); 11 typedef long long LL; 12 struct node 13 { 14 int to, next; 15 }edge[maxn*2]; 16 int head[2][maxn], vis[maxn], tot, flag; 17 LL res; 18 19 void Add (int from, int to) 20 { 21 edge[tot].to = to; 22 edge[tot].next = head[0][from]; 23 head[0][from] = tot ++; 24 head[1][from] ++; 25 } 26 27 void dfs (int u) 28 { 29 int k, cnt; 30 k = cnt = 0; 31 vis[u] = 1; 32 for (int i=head[0][u]; i!=-1; i=edge[i].next) 33 { 34 35 int v = edge[i].to; 36 if (vis[v]) 37 continue; 38 if (!vis[v] && head[1][v]==1) 39 cnt ++; 40 else 41 dfs (v); 42 k ++; 43 } 44 if (k - cnt > 2) 45 { 46 res = 0; 47 return; 48 } 49 if (k != cnt) 50 res = (res * 2) % mod; 51 while (cnt) 52 { 53 res = (res * cnt) % mod; 54 cnt --; 55 } 56 } 57 int main () 58 { 59 int t, n, l = 0; 60 scanf ("%d", &t); 61 62 while (t --) 63 { 64 scanf ("%d", &n); 65 memset (head[0], -1, sizeof(head[0])); 66 memset (head[1], 0, sizeof(head[1])); 67 memset (vis, 0, sizeof(vis)); 68 tot = flag = 0; 69 70 for (int i=1; i<n; i++) 71 { 72 int u, v; 73 scanf ("%d %d", &u, &v); 74 Add (u, v); 75 Add (v, u); 76 } 77 res = 2; 78 dfs (1); 79 printf ("Case #%d: %lld ", ++l, n==1?1:res); 80 } 81 return 0; 82 }