题意:在一棵有n个节点的树上放编号从1到n的麻将,要求每个点的儿子节点之间的编号连续,每棵子树内的编号连续。

解法:手推一组样例之后就可以得到如下结论然后从根节点一边讨论一边搜就好了。

当一个节点只有一个儿子的时候,如果儿子是叶子节点则只有一种放法,如果儿子不是叶子节点则有两种放法。

当一个节点有两个儿子的时候,一定有两种放法。

当一个儿子有三个儿子及以上的时候,假设有k个儿子,如果非叶子节点m的个数为0则有k!种放法,如果m为1,则有2 × (k - 1)!种放法,如果m为2,则有2 × (k - 2)!种放法,如果m > 2则不存在合法情况。

将所有情况相乘即为答案。

代码:

代码是队友写的……这么鬼畜的变量名才不是我起的呢233

哦对了……要手动扩栈不然会RE

#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <set>
#include <map>
#include <vector>
#include <limits.h>
using namespace std;
typedef long long LL;
#define MAXN 100010//1e5
const LL mod = (LL)1e9 + 7;
int t, n, cas;
vector<int> edge[MAXN];
bool vis[MAXN];
LL ans;
LL A[MAXN];
void init() {
for(int i = 0; i <= n; i++) {
edge[i].clear();
}
edge[0].push_back(1);
edge[1].push_back(0);
memset(vis, false, sizeof vis);
vis[0] = true;
ans = 1LL;
}
void DFS(int u) {
int len = edge[u].size();
if((len == 1 && u != 0) || ans == 0LL) return ;
if(len - 1 == 1 || u == 0) {
for(int i = 0; i < len; i++) {
int v = edge[u][i];
if(!vis[v]) {
if(edge[v].size() - 1 > 0) {
ans = (ans * 2LL) % mod;
vis[v] = true;
if(ans == 0LL) return;
DFS(v);
}
}
}
} else if(len - 1 == 2) {
ans = (ans * 2LL) % mod;
for(int i = 0; i < len; i++) {
int v = edge[u][i];
if(vis[v]) continue;
vis[v] = true;
if(ans == 0LL) return;
DFS(v);
}
} else if(len - 1 >= 3) {
vector<int> son;
int cnt = 0;
int dayu0 = 0;
for(int i = 0; i < len; i++) {
int v = edge[u][i];
if(vis[v]) continue;
son.push_back(v);
if(edge[v].size() - 1 > 0) dayu0++;
}
cnt = son.size();
if(dayu0 == 0) {
ans = (ans * A[cnt]) % mod;
} else if(dayu0 == 1) {
ans = (ans * 2LL) % mod;
ans = (ans * A[cnt - 1]) % mod;
} else if(dayu0 == 2) {
ans = (ans * 2LL) % mod;
ans = (ans * A[cnt - 2]) % mod;
} else {
ans = 0LL; return ;
}
for(int i = 0; i < cnt; i++) {
int v = son[i];
vis[v] = true;
if(ans == 0LL) return ;
DFS(v);
}
}
}
int main() {
scanf("%d", &t);
A[1] = 1LL;
for(LL i = 2; i <= 100000LL; i++) {
A[i] = A[i - 1] * i % mod;
}
while(t--) {
scanf("%d", &n);
init();
int u, v;
for(int i = 0; i < n - 1; i++) {
scanf("%d%d", &u, &v);
edge[u].push_back(v);
edge[v].push_back(u);
}
DFS(0);
printf("Case #%d: %I64d\n", ++cas, ans);
}
return 0;
}

  

HDU 5379 Mahjong tree的更多相关文章

  1. Hdu 5379 Mahjong tree (dfs + 组合数)

    题目链接: Hdu 5379 Mahjong tree 题目描述: 给出一个有n个节点的树,以节点1为根节点.问在满足兄弟节点连续 以及 子树包含节点连续 的条件下,有多少种编号方案给树上的n个点编号 ...

  2. HDU 5379 Mahjong tree(dfs)

    题目链接:pid=5379">http://acm.hdu.edu.cn/showproblem.php? pid=5379 Problem Description Little su ...

  3. HDU 5379 Mahjong tree(树的遍历&amp;组合数学)

    本文纯属原创,转载请注明出处.谢谢. http://blog.csdn.net/zip_fan 题目传送门:http://acm.hdu.edu.cn/showproblem.php? pid=537 ...

  4. HDU 5379——Mahjong tree——————【搜索】

    Mahjong tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  5. 2015 Multi-University Training Contest 7 hdu 5379 Mahjong tree

    Mahjong tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Tota ...

  6. 2015多校第7场 HDU 5379 Mahjong tree 构造,DFS

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5379 题意:一颗n个节点n-1条边的树,现在要给每个节点标号(1~n),要求:(1)每一层的兄弟节点的 ...

  7. HDU 5379 Mahjong tree dfs+组合数学

    题意:给你一棵树来分配号码,要求是兄弟节点连续并且每一棵子树连续. 思路:因为要求兄弟和子树都是连续的,所以自己打下草稿就可以发现如果一个节点有3个或3个以上的非叶子结点,那么就无论如何也不能达到目的 ...

  8. Mahjong tree (hdu 5379 dfs)

    Mahjong tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Tot ...

  9. 【HDOJ 5379】 Mahjong tree

    [HDOJ 5379] Mahjong tree 往一颗树上标号 要求同一父亲节点的节点们标号连续 同一子树的节点们标号连续 问一共同拥有几种标法 画了一画 发现标号有二叉树的感觉 初始标号1~n 根 ...

随机推荐

  1. 从后端到页面:如何全方位监控 Ruby 应用?

    [编者按]本文参考技术分享 ,由 OneAPM 工程师补充整理,并且已经征得原作者的同意. 为什么选择 OneAPM ? 在性能监控领域,业界比较有名的是 New Relic 还有 Appdynami ...

  2. C#操作config文件

    以下是app.config或web.config的定义,定义了一个参数,键为Isinit,值为false <?xml version="1.0"?> <confi ...

  3. Longest Repeated Sequence【微软编程一小时-题目2】

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 You are given a sequence of integers, A = a1, a2, ... an. A c ...

  4. C#中 ? 和?? 的用法

    C#中 ?? 和? 的意思 1.? 如果直接定义一个 值类型,给负值null:就会提示“无法将 Null转换成‘值类型(比如:int)’,因为他是一种不可为null的值 de类型” 例如 int in ...

  5. HDU 4143 A Simple Problem(枚举)

    题目链接 题意 : 就是给你一个数n,让你输出能够满足y^2 = n +x^2这个等式的最小的x值. 思路 : 这个题大一的时候做过,但是不会,后来学长给讲了,然后昨天比赛的时候二师兄看了之后就敲了, ...

  6. lintcode:Add Binary 二进制求和

    题目: 二进制求和 给定两个二进制字符串,返回他们的和(用二进制表示). 样例 a = 11 b = 1 返回 100 解题: 和求两个链表的和很类似 考虑进位,考虑最后一项的进位 0+0 = 0 不 ...

  7. Tomcat部署Web应用方法总结

    转载:http://m.blog.csdn.net/blog/u012516903/15741727 Tomcat部署Web应用方法总结 在Tomcat中部署Java Web应用程序有两种方式:静态部 ...

  8. 在浏览器控制台输出内容 console.log(string);

    在浏览器控制台中写如数据 1添加    <script type="text/javascript">djConfig = { isDebug: true };< ...

  9. jQuery编程基础精华02(属性、表单过滤器,元素的each,表单选择器,子元素过滤器(*),追加方法,节点,样式操作)

    属性.表单过滤器 属性过滤选择器: $("div[id]")选取有id属性的<div> $("div[title=test]")选取title属性为 ...

  10. Git教程之版本回退(4)

    现在,我们已经学会了修改文件,然后把修改提交到Git版本库,现在再次修改readme.txt文件如下: