• 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 }
  • 相关阅读:
    [thinkphp] 是如何输出一个页面的
    [thinkphp] 获取根目录绝对路径
    onethink 插件模板定位
    win7 安全模式开启声音
    百度贴吧楼层评论地址
    第一天问题
    [php] 解析JSON字符串
    NDK编译时两 .so之间调用问题
    CDN问题积累
    C++模板特化
  • 原文地址:https://www.cnblogs.com/macinchang/p/4727110.html
Copyright © 2020-2023  润新知