HDU 5379 Mahjong tree dfs+组合数学

题意:给你一棵树来分配号码,要求是兄弟节点连续并且每一棵子树连续。

思路:因为要求兄弟和子树都是连续的,所以自己打下草稿就可以发现如果一个节点有3个或3个以上的非叶子结点,那么就无论如何也不能达到目的。

    现在假设一个节点有x个非叶的子节点,y个叶子子节点。

    若x = 0,对于这棵子树,父节点只能取两端的号码才能使兄弟节点连续,y个叶子节点则有一个全排列,因此当前的方案数有 y! * 2

    若x = 1,且这颗非叶子节点构成的子树的方案数是f[a],方案数为 y! * f[a] * 2

    若x = 2,且这两棵非叶子结点的方案数分别是f[a]和f[b], 方案数为 y! * f[a] * f[b]

   

多校的题确实感觉有点难(不是指这道....),还是希望自己努点力,争取这一段时间把多校的题全部解决,,,除非特别难的。。。

 1 #pragma comment(linker, "/STACK:102400000,102400000")
 2 #include <iostream>
 3 #include <cstdio>
 4 #include <fstream>
 5 #include <algorithm>
 6 #include <cmath>
 7 #include <deque>
 8 #include <vector>
 9 #include <queue>
10 #include <string>
11 #include <cstring>
12 #include <map>
13 #include <stack>
14 #include <set>
15 #define LL long long
16 #define MAXN 100005
17 #define INF 0x3f3f3f3f
18 #define MOD 1000000007
19 #define eps 1e-8
20 using namespace std;
21 bool vis[MAXN];
22 vector<int> G[MAXN];
23 LL fact[MAXN];
24 LL res;
25 void dfs(int x){
26     vis[x] = true;
27     int single = 0, son = 0;
28     //LL res = 1;
29     int m = G[x].size();
30     for(int i = 0; i < m; i++){
31         int y = G[x][i];
32         if(vis[y]) continue;
33         vis[y] = true;
34         son++;
35         if(G[y].size() == 1){
36             single++;
37         }
38         else{
39             dfs(y);
40         }
41     }
42     if(son - single > 2){
43         res = 0;
44         return;
45     }
46     else if(son - single == 2){
47         res = res * fact[single] % MOD;
48     }
49     else{
50         res = res * 2LL * fact[single] % MOD;
51     }
52 }
53 int main()
54 {
55 #ifndef ONLINE_JUDGE
56     freopen("in.txt", "r", stdin);
57     //freopen("out.txt", "w", stdout);
58 #endif // OPEN_FILE
59     int T;
60     scanf("%d", &T);
61     int cas = 1;
62     fact[0] = 1;
63     for(int i = 1; i <= 100000; i++){
64         fact[i] = fact[i - 1] * (LL)i % MOD;
65     }
66     int n;
67     while(T--){
68         scanf("%d", &n);
69         int x, y;
70         for(int i = 0; i <= n; i++){
71             G[i].clear();
72         }
73         memset(vis, 0, sizeof(vis));
74         for(int i = 1; i < n; i++){
75             scanf("%d%d", &x, &y);
76             G[x].push_back(y);
77             G[y].push_back(x);
78         }
79         //vis[1] = true;
80         res = 1;
81         //LL ans = dfs(1);
82         dfs(1);
83         if(n == 1){
84             res = 1;
85         }
86         printf("Case #%d: %I64d
", cas++, res);
87     }
88 }
原文地址:https://www.cnblogs.com/macinchang/p/4727110.html