题目大概是说给一棵树的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. 浅谈setTimeout函数和setInterval函数

    前几天学了js,看到了两个非常有趣的函数,他们分别是setTimeout函数和setInterval函数,这两个函数能使网页呈现非常一些网页中比较常见的效果,比如说图片轮播,等一些非常好玩的效果.下面 ...

  2. sql分组取第一条数据

    sq分组取第一条数据的一个方法: select * from ( select row_number() over(partition by ID order by ID) as rownum , * ...

  3. [Effective JavaScript 笔记] 第6条:了解分号插入的局限

    分号可以省略 js可以在语句结束不强制加分号.(建议还是添加,不添加分号往往会出现不易发现的BUG) function Point(x,y){ this.x=x||0; this.y=y||0; } ...

  4. 【VirtualBox】VirtualBox的桥接网络模式,为啥网络不稳定?

    网桥模式访问外网非常慢,经常卡死,ping时断时续 七搞八搞,反复重启了几次 TMD  就好了,也不知道什么情况,VirtualBox还是不太好使啊..... 网桥模式 设置 如下: 参考资料: ht ...

  5. 【leetcode】Combination Sum II

    Combination Sum II Given a collection of candidate numbers (C) and a target number (T), find all uni ...

  6. bootbox显示中文的按钮

    $("selector").on('click',function(){ bootbox.confirm({ title : "请确认", buttons: { ...

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

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

  8. Java内存分配和内存管理

    首先是概念层面的几个问题: Java中运行时内存结构有哪几种? Java中为什么要设计堆栈分离? Java多线程中是如何实现数据共享的? Java反射的基础是什么? 然后是运用层面: 引用类型变量和对 ...

  9. Cocos2d-JS游戏导演

    什么是游戏的导演 具体来说,Cocos2d-JS中的导演是一个对象,它负责设置游戏的运行环境,控制游戏的住循环并且管理场景和场景的切换. 导演的任务 Cocos2d-JS中导演对象名为:cc.dire ...

  10. 51nod 1264 线段相交

    题目:传送门. 题意:给两条线段,有一个公共点或有部分重合认为相交,问他们是否相交. 题解:这属于非规范相交的情况,模板题. #include <iostream> #include &l ...