题意:在一棵有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. Java的synchronized关键字:同步机制总结

    JAVA中synchronized关键字能够作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块.搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程 ...

  2. package.json 字段全解析 share

    Name 必须字段. 小提示: 不要在name中包含js, node字样: 这个名字最终会是URL的一部分,命令行的参数,目录名,所以不能以点号或下划线开头: 这个名字可能在require()方法中被 ...

  3. crontab 不能执行git命令问题备忘

    这问题够隐蔽,折腾了近两个小时. 命令 git checkout tagname 手工执行都正常 但在crontab运行时发现分支一直切不过去. 后来告诉是crontab默认的 path  设置和系统 ...

  4. mac 设置 ll 等alias 并永久生效

    往上看了在.bash_profile中配置 然后 source  的方法, 试过了, 只是当前的终端有效,当电脑重启或者关闭终端就失效了,只好看看 mac 的 profile 代码 # System- ...

  5. leetcode:两个数的和||

    两个数的和|| 给定一个排序数组,求出其中两个数的和等于指定target时,这两个数在原始数组中的下标,返回的下标从1开始 解题 原始数组已经是升序的,找出其中两个数的和等于target 定义两个指针 ...

  6. hdu 1002 java 大数相加

    package Main; //import java.io.InputStream; import java.math.BigDecimal; import java.util.Scanner; p ...

  7. C#操作.csv文件Demo

    1.使用OleDB操作.csv文件,比较费时 public static DataTable GetDataTableFromCsv(string path,bool isFirstRowHeader ...

  8. word文档标题级别批量更改——批量降级与升级实例

    word文档标题级别批量更改——批量降级与升级实例   word文档标题级别批量更改——批量降级实例 2012年12月21日16:30:44 现有一个3级文档结构的word文档,如下图所示 先需要将上 ...

  9. OpenCV源码阅读(2)---matx.h---函数的内联实现

    外部矩阵计算函数 namespace internal { template<typename _Tp, int m> struct Matx_DetOp { double operato ...

  10. epoll和poll效率差异

    http://blog.163.com/sky20081816@126/blog/static/164761023201073033517435/ 百度“epoll和poll”