题目大概是说给一棵树的n个结点从1到n编号,要求每个结点的编号大于其父结点,问有多少种编号方式。

想了挺久的,感觉有点眉目,最后画了下样例YY出解法:

  • 首先求出以每个结点为根的子树大小,记为size[u],这个DFS一遍就可以求出来;
  • 接下来,dp[u]表示给以u为根的子树size[u]个编号有几种编号方案 
  • 然后考虑转移方程:
    • 比如一个结点u有3个儿子v1,v2,v3,那么u子树有size[u]个编号,编号最小的就属于u,剩下size[u]-1分配给u的三个子树,分配方式就有:

C(size[u]-1,size[v1])*C(size[u]-1-size[v1],size[v2])*C(size[u]-1-size[v1]-size[v2],size[v3])

    • 而v1、v2和v3子树对它们被分配的编号又分别有dp[v1]、dp[v2]和dp[v3]种编号方案,因此u子树的size[u]个编号总共的编号方式即dp[u]是:

dp[u] = dp[v1]*dp[v2]*dp[v3]*C(size[u]-1,size[v1])*C(size[u]-1-size[v1],size[v2])*C(size[u]-1-size[v1]-size[v2],size[v3])

于是就是这样用DP求解的。另外C(n,m)可以利用组合数的递推式C(n,m)=C(n-1,m)+C(n-1,m-1)预处理出来。

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct Edge{
int v,next;
}edge[];
int NE,head[];
void addEdge(int u,int v){
edge[NE].v=v; edge[NE].next=head[u]; head[u]=NE++;
}
int n,size[];
long long C[][],d[];
int getSize(int u){
if(size[u]) return size[u];
int res=;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
res+=getSize(v);
}
return size[u]=res;
}
long long dfs(int u){
if(d[u]) return d[u];
long long res=;
int cnt=size[u]-;
for(int i=head[u]; i!=-; i=edge[i].next){
int v=edge[i].v;
res*=(dfs(v)*C[cnt][size[v]])%;
res%=;
cnt-=size[v];
}
return res;
}
int main(){
for(int i=; i<; ++i) C[i][]=;
for(int i=; i<; ++i){
for(int j=; j<=i; ++j) C[i][j]=(C[i-][j]+C[i-][j-])%;
}
int t,a,b;
scanf("%d",&t);
for(int cse=; cse<=t; ++cse){
NE=;
memset(head,-,sizeof(head));
bool uroot[]={};
scanf("%d",&n);
for(int i=; i<n; ++i){
scanf("%d%d",&a,&b);
addEdge(a,b);
uroot[b]=;
}
int root;
for(int i=; i<=n; ++i){
if(!uroot[i]){
root=i;
break;
}
}
memset(size,,sizeof(size));
getSize(root);
memset(d,,sizeof(d));
printf("Case %d: %lld\n",cse,dfs(root));
}
return ;
}

LightOJ1382 The Queue(树形DP)的更多相关文章

  1. lightoj 1382 - The Queue(树形dp)

    题目链接:http://www.lightoj.com/volume_showproblem.php?problem=1382 题解:简单的树形dp加上组合数学. #include <iostr ...

  2. poj3417 LCA + 树形dp

    Network Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 4478   Accepted: 1292 Descripti ...

  3. COGS 2532. [HZOI 2016]树之美 树形dp

    可以发现这道题的数据范围有些奇怪,为毛n辣么大,而k只有10 我们从树形dp的角度来考虑这个问题. 如果我们设f[x][k]表示与x距离为k的点的数量,那么我们可以O(1)回答一个询问 可是这样的话d ...

  4. 树形DP

    切题ing!!!!! HDU  2196 Anniversary party 经典树形DP,以前写的太搓了,终于学会简单写法了.... #include <iostream> #inclu ...

  5. BZOJ 2286 消耗战 (虚树+树形DP)

    给出一个n节点的无向树,每条边都有一个边权,给出m个询问,每个询问询问ki个点,问切掉一些边后使得这些顶点无法与顶点1连接.最少的边权和是多少.(n<=250000,sigma(ki)<= ...

  6. bzoj2500: 幸福的道路(树形dp+单调队列)

    好题.. 先找出每个节点的树上最长路 由树形DP完成 节点x,设其最长路的子节点为y 对于y的最长路,有向上和向下两种情况: down:y向子节点的最长路g[y][0] up:x的次长路的g[x][1 ...

  7. HDU 1520 树形dp裸题

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

  8. HDU 1561 树形DP入门

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

  9. HDU 4123 (2011 Asia FZU contest)(树形DP + 维护最长子序列)(bfs + 尺取法)

    题意:告诉一张带权图,不存在环,存下每个点能够到的最大的距离,就是一个长度为n的序列,然后求出最大值-最小值不大于Q的最长子序列的长度. 做法1:两步,第一步是根据图计算出这个序列,大姐头用了树形DP ...

  10. poj 2342 Anniversary party 简单树形dp

    Anniversary party Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3862   Accepted: 2171 ...

随机推荐

  1. java笔记--关于线程死锁

    关于线程死锁 什么是死锁: 在编写多线程的时候,必须要注意资源的使用问题,如果两个或多个线程分别拥有不同的资源, 而同时又需要对方释放资源才能继续运行时,就会发生死锁. 简单来说:死锁就是当一个或多个 ...

  2. [BZOJ3670][UOJ#5][NOI2014]动物园

    [BZOJ3670][UOJ#5][NOI2014]动物园 试题描述 近日,园长发现动物园中好吃懒做的动物越来越多了.例如企鹅,只会卖萌向游客要吃的.为了整治动物园的不良风气,让动物们凭自己的真才实学 ...

  3. Java报错原因汇总

    1. java.lang.nullpointerexception 这个异常大家肯定都经常遇到,异常的解释是"程序 遇上了空指针",简单地说就是调用了未经初始化的对象或者是不存在的 ...

  4. 2015安徽省赛 A.First Blood

    题目描述 盖伦是个小学一年级的学生,在一次数学课的时候,老师给他们出了一个难题: 老师给了一个正整数 n,需要在不大于n的范围内选择三个正整数(可以是相同的),使它们三个的最小公倍数尽可能的大.盖伦很 ...

  5. 《linux备份与恢复之二》3.19 dump(文件系统备份)

    <Linux指令从初学到精通>第3章文件管理,本章介绍了许多常用命令,如cp.ln.chmod.chown.diff.tar.mv等,因为这些都与文件管理相关,在日常的使用中经常用到,因此 ...

  6. win平台检查内存泄露

    int main() { _CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); _CrtSetBre ...

  7. DP:Corn Fields(POJ 3254)

    北大教你如何高效养牛(误)(点我查看)  2015-08-21: 问题的大意就是有一片稻田,里面有很多坑,你要在上面种稻谷,然后呢田里面还会养牛,牛不喜欢扎堆吃饭,所以呢你种的稻谷要间隔种在坑里面,所 ...

  8. codeforces 475A.Bayan Bus 解题报告

    题目链接:http://codeforces.com/problemset/problem/475/A 题目意思:输入一个整数 k(0 ≤ k ≤ 34),表示participants的人数,需要在一 ...

  9. [Android Studio] 使用本地 aar 文件

    导出aar 首先Android Library项目的gradle脚本只需要在开头声明 apply plugin: 'com.android.library' 之后就和导出apk文件一样的方法,执行 . ...

  10. C++类的成员函数使用的一些小总结

    From: http://blog.csdn.net/xiayefanxing/article/details/7607506 这一阵做项目代码开发的时候,用到了在一个C++文件中使用另一个类的成员函 ...