任意一棵子树上节点的编号连续,每个节点的所有二字节点连续,求编号方案的总数。

稍微分析一下可知

  • 每个节点的非叶子节点个数不能多于两个,否则这个子树无解,从而整棵树都无解。
  • 每棵子树将所有节点按照编号从小到大排序,根节点要么在最左端,要么在最右端,而且这两种情况相等。(后面会有具体分析)

设size(u)表示以节点u为根的子树中节点总数。

d(u)表示用1 ~ size(u)给以u为根的子树编号的合法方案数,考虑下面几种情况:

①:  u是叶子节点,方案数为1.

②:  u的所有儿子节点都是叶子节点,那么所有儿子节点连续(假设儿子节点有S个),u只能放在所有儿子节点的前面或者最后面。所以方案数就是2(S!),因为儿子节点之间互不影响可以任意排列。

③:  u只有一个非叶儿子节点v。

方案数为:2 * d(v) * S!

首先子树v的排列方案有d(v)种,子树v的排列确定下来以后,而且v一定是在这个排列的某一端,由于所有儿子节点连续,所以这S个v的叶子兄弟必须紧挨着v,所以有S!种,此时只有u的位置没有确定好,u可以放在排列的开头或者末尾,所以答案最终要乘2.

④:  u有两个非叶子儿子节点v1, v2.

首先u的所有儿子节点是要连续的,所以v1, v2和他俩的叶子兄弟要在连续的一段;而且还要满足,v1这棵子树连续,v2这棵子树连续,所以v1和v2注定只能排在在u的儿子中的两端。

排列大概就是这样的,因为v1排在左端的方案数为d(v1) / 2,同样地v2排在右端的方案数为d(v2) / 2,叶子兄弟在v1和v2之间任意排列,u排在左右两端都行。

所以上图表示总的方案数为 d(v1) / 2 * d(v2) / 2 * S! * 2 = d(v1) * d(v2) / 2 * S!

不要急,还有一半情况没考虑到。就是v1子树排在右边,v2子树排在左边,所以上面的答案还要乘个2,得到 d(v1) * d(v2) * S!

⑤:  非叶子节点数多于两个,开头已经说过了,无解。

因为数据比较大,要手动扩栈然后用C++提交。

 #pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std; typedef long long LL; const int maxn = + ;
const LL MOD = ; vector<int> G[maxn]; int sz[maxn];
LL d[maxn], fac[maxn]; void dfs(int u, int fa)
{
sz[u] = ;
LL T = ;
int c1 = , c2 = ;
for(int i = ; i < G[u].size(); i++)
{
int v = G[u][i];
if(v == fa) continue;
dfs(v, u);
sz[u] += sz[v]; if(d[v] == ) { d[u] = ; return ; } if(sz[v] > ) { c1++; T = (T * d[v]) % MOD; }
else c2++; if(c1 > ) { d[u] = ; return ; }
} if(sz[u] == ) { d[u] = ; return ; }
if(c1 < ) d[u] = (2LL * fac[c2] * T) % MOD;
else d[u] = (fac[c2] * T) % MOD;
} int main()
{
fac[] = ;
for(int i = ; i < maxn; i++) fac[i] = (fac[i - ] * i) % MOD; int T; scanf("%d", &T);
for(int kase = ; kase <= T; kase++)
{
int n; scanf("%d", &n);
for(int i = ; i <= n; i++) G[i].clear();
for(int i = ; i < n; i++)
{
int u, v; scanf("%d%d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
} printf("Case #%d: ", kase); if(n == ) { puts(""); continue; } dfs(, );
printf("%I64d\n", d[]);
} return ;
}

代码君

HDU 5379 树形DP Mahjong tree的更多相关文章

  1. hdu 4123 树形DP+RMQ

    http://acm.hdu.edu.cn/showproblem.php? pid=4123 Problem Description Bob wants to hold a race to enco ...

  2. 刷题总结——Tree chain problem(HDU 5293 树形dp+dfs序+树状数组)

    题目: Problem Description Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There ar ...

  3. codevs 1380/HDU 1520 树形dp

    1380 没有上司的舞会 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 题解 查看运行结果 回到问题 题目描述 Description Ural大学有N个职员 ...

  4. HDU 1520 树形dp裸题

    1.HDU 1520  Anniversary party 2.总结:第一道树形dp,有点纠结 题意:公司聚会,员工与直接上司不能同时来,求最大权值和 #include<iostream> ...

  5. HDU 1561 树形DP入门

    The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Oth ...

  6. HDU 2196树形DP(2个方向)

    HDU 2196 [题目链接]HDU 2196 [题目类型]树形DP(2个方向) &题意: 题意是求树中每个点到所有叶子节点的距离的最大值是多少. &题解: 2次dfs,先把子树的最大 ...

  7. HDU 1520 树形DP入门

    HDU 1520 [题目链接]HDU 1520 [题目类型]树形DP &题意: 某公司要举办一次晚会,但是为了使得晚会的气氛更加活跃,每个参加晚会的人都不希望在晚会中见到他的直接上司,现在已知 ...

  8. HDU 5834 [树形dp]

    /* 题意:n个点组成的树,点和边都有权值,当第一次访问某个点的时候获得利益为点的权值 每次经过一条边,丢失利益为边的权值.问从第i个点出发,获得的利益最大是多少. 输入: 测试样例组数T n n个数 ...

  9. hdu 4267 树形DP

    思路:先dfs一下,找出1,n间的路径长度和价值,回溯时将该路径长度和价值清零.那么对剩下的图就可以直接树形dp求解了. #include<iostream> #include<al ...

随机推荐

  1. nuxt实践

    利用手脚架搭起来的服务端渲染实例目录结构.nuxtassets 未编译的静态资源如 LESS.SASS 或 JavaScriptcomponents 用于组织应用的 Vue.js 组件middlewa ...

  2. 【复习笔记】HTML基础

    编码 HTML LANG标注整体文档语言 常用编码:ASCII.GB2312.UTF-8 中文编码解决: 1.浏览器要用一个编码表去看你的文件<meta charset="utf-8& ...

  3. 在jquery事件中修改Angular的model

    HTML代码如下 <!DOCTYPE html> <html ng-app="qm"> <body> <input type=" ...

  4. 设置DIV随滚动条滚动而滚动

    有段时间没有碰Web端了,最近做了个功能,需要做个DIV随滚动条滚动而滚动,mark一下: 源码: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1 ...

  5. 【虚拟机-远程连接】Azure Linux 虚拟机常见导致无法远程的操作

    对Azure虚拟机的一些操作可能会导致无法远程连接,本文罗列了以下导致不能远程连接的场景: 场景1 - 在虚拟机配置IP地址或MAC地址 场景2 - 错误地修改服务的配置文件 场景3 - 误设置防火墙 ...

  6. SQL Server 2016,2014 “无法找到数据库引擎启动句柄”

    当我决定安装SharePoint 2016 IT预览版时,我想我应该将它安装在Windows Server 2016技术预览版以及SQL Server 2016社区技术预览版(CTP)上.我敢打赌,你 ...

  7. WinForm form属性

    一.布局 Autostroll   控件内容大于可见区域是否自动显示滚动条 Maximumsize 窗体可调到最大尺寸 minimumsize  窗体可调到最小尺寸 size  窗体看到的尺寸 Sta ...

  8. python基础一 day15 作业

    3.处理文件,用户指定要查找的文件和内容,将文件中包含要查找内容的每一行都输出到屏幕def check_file(filename,aim): with open(filename,encoding= ...

  9. WINDOWS-基础:SafeArray的使用方法

    1 SafeArray的作用 使用SafeArray SafeArray是VB中的数组存储方式.通过SafeArray,可以在VC++和VB间相互调用. SafeArray也是Automation中的 ...

  10. samba修改smb.conf后,不需要重启服务,就可生效

    在修改完smb.conf后,不需要重启服务.在Centos7.3与Ubuntu18.04上验证都没有问题. 猜测可能的原因:samba是在客户端进行连接时,smb服务程序读取smb.conf配置文件信 ...