计蒜客 Red Black Tree(树形DP)

You are given a rooted tree with n nodes. The nodes are numbered 1..n. The root is node 1, and m of the nodes are colored red, the rest are black.

You would like to choose a subset of nodes such that there is no node in your subset which is an ancestor of any other node in your subset. For example, if A is the parent of B and B is the parent of C, then you could have at most one of A, B or C in your subset. In addition, you would like exactly k of your chosen nodes to be red.

If exactly mm of the nodes are red, then for all k = 0..m, figure out how many ways you can choose subsets with k red nodes, and no node is an ancestor of any other node.

Input Format

Each input will consist of a single test case.

Note that your program may be run multiple times on different inputs.

Each test case will begin with a line with two integers n(1≤n≤2×10^5) and m(0≤m≤min(10^3,n)), where n is the number of nodes in the tree, and m is the number of nodes which are red. The nodes are numbered 1..n.

Each of the next n - 1 lines will contain a single integer p(1≤p≤n), which is the number of the parent of this node. The nodes are listed in order, starting with node 2, then node 3, and so on. Node 1 is skipped, since it is the root. It is guaranteed that the nodes form a single tree, with a single root at node 1 and no cycles.

Each of the next m lines will contain single integer r(1≤r≤n). These are the numbers of the red nodes. No value of r will be repeated.

Output Format

Output m + 1 lines, corresponding to the number of subsets satisfying the given criteria with a number of red nodes equal to k = 0..m, in that order. Output this number modulo 10^9 + 7.

样例输入1

4 1
1
1
1
3

样例输出1

5
4

样例输入2

4 4
1
1
1
1
2
3
4

样例输出2

1
4
3
1
0

样例输入3

14 4
1
2
1
2
3
4
5
5
13
8
10
4
4
8
3
12
13

样例输出3

100
169
90
16
0

题意

一棵树,n个点,其中有m个红色,其余为黑点,1为根,选1个点集合,集合内的任意两点不互为祖先,问集合内红色节点的个数为0-m的方案数。

题解

dp[root][m]代表根为root的子树红色节点为m的方案数。

不选root,dp[root][0]=1,考虑子树son的情况,考虑h[M]代表组成M的方案数,相当于每次一颗子树把里面的所有红色节点一个一个压进去,类似于背包。

选root,dp[root][red[root]]++,相当于下面都不能选。

代码

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=200005;
 4 const int M=1005;
 5 const int MD=1000000007;
 6 int dp[N][M],h[M],red[N],sz[N];
 7 int n,m;
 8 vector<int>G[N];
 9 void dfs(int u){
10     dp[u][0]=1;
11     sz[u]=red[u];
12     for(int i=0;i<G[u].size();i++) {
13         int v=G[u][i];
14         dfs(v);
15         int up=min(sz[u]+sz[v],m);
16         for(int j=0;j<=up;j++)h[j]=0;
17         for(int j=0;j<=sz[v];j++)
18             for(int k=0;k<=sz[u]&&j+k<=up;k++)
19                 h[j+k]=(h[j+k]+1LL*dp[v][j]*dp[u][k])%MD;
20         sz[u]+=sz[v];
21         for(int j=0;j<=sz[u];j++)dp[u][j]=h[j];
22     }
23     dp[u][red[u]]=(dp[u][red[u]]+1)%MD;
24 }
25 int main() {
26     scanf("%d%d",&n,&m);
27     for(int i=2,u;i<=n;i++) {
28         scanf("%d",&u);
29         G[u].push_back(i);
30     }
31     for(int i=0,x;i<m;i++) {
32         scanf("%d",&x);
33         red[x]=1;
34     }
35     dfs(1);
36     for(int i=0;i<=m;i++)
37         printf("%d\n",dp[1][i]);
38     return 0;
39 }

原文地址:https://www.cnblogs.com/taozi1115402474/p/11300110.html

时间: 2024-08-29 21:05:09

计蒜客 Red Black Tree(树形DP)的相关文章

计蒜客- AC Challenge 状压dp

题目链接:https://nanti.jisuanke.com/t/30994 Dlsj is competing in a contest with n(0<n≤20)n (0 < n \le 20)n(0<n≤20) problems. And he knows the answer of all of these problems. However, he can submit iii-th problem if and only if he has submitted (and

计蒜客 Flashing Fluorescents(状压DP)

You have nn lights, each with its own button, in a line. Pressing a light’s button will toggle that light’s state; if the light is on, it will turn off, and if the light is off, it will turn on. The lights change at 1 second timesteps. You can press

计蒜客 无脑博士和他的试管们

无脑博士有三个容量分别是A,B,C升的试管,A,B,C分别是三个从1到20的整数,最初,A和B试管都是空的,而C试管是装满硫酸铜溶液的.有时,无脑博士把硫酸铜溶液从一个试管倒到另一个试管中,直到被灌试管装满或原试管空了.当然每一次灌注都是完全的.由于无脑博士天天这么折腾,早已熟练,溶液在倒的过程中不会有丢失. 写一个程序去帮助无脑博士找出当A是个是空的时候,C试管中硫酸铜溶液所剩量的所有可能性. 输入包括一行,为空格分隔开的三个数,分别为整数A,B和C. 输出包括一行,升序地列出当A试管是空的时

Bestcoder round #65 &amp;&amp; hdu 5593 ZYB&#39;s Tree 树形dp

Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 354    Accepted Submission(s): 100 Problem Description ZYB has a tree with N nodes,now he wants you to solve the numbers of nodes distanced no m

codeforces161D - Distance in Tree 树形dp

题意:给你一棵树,问你树中距离为k的有多少种情况. 解题思路:树形dp  维护每个节点(1-K)深度的情况, 解题代码: 1 // File Name: 161d.cpp 2 // Author: darkdream 3 // Created Time: 2014年08月03日 星期日 19时20分10秒 4 5 #include<vector> 6 #include<list> 7 #include<map> 8 #include<set> 9 #incl

hdu5593/ZYB&#39;s Tree 树形dp

ZYB's Tree Memory Limit: 131072/131072 K (Java/Others) 问题描述 ZYBZYB有一颗NN个节点的树,现在他希望你对于每一个点,求出离每个点距离不超过KK的点的个数. 两个点(x,y)(x,y)在树上的距离定义为两个点树上最短路径经过的边数, 为了节约读入和输出的时间,我们采用如下方式进行读入输出: 读入:读入两个数A,BA,B,令fa_ifa?i??为节点ii的父亲,fa_1=0fa?1??=0;fa_i=(A*i+B)\%(i-1)+1fa

简单斐波那契——计蒜客(4)

题目来自“计蒜客”第4题. 解算法题之前,务必先写出与之对应的数学表达式,用于描述算法. 数学描述如图: 根据“数学描述“,写出代码如下: #include <stdio.h> int main() { int N =0 ; scanf("%d", &N); int i, fn1 = 1, fn2 = 0, fn; switch(N) { case 0: printf("0"); break; case 1: printf("1&quo

计蒜客普及组模拟赛

今天没事闲的看到计蒜客有个普及组模拟赛,就当练了练手去打了,成绩低的可怜...400分崩成280分AK梦想化作泡影 第一题 同学的爱好 链接:https://nanti.jisuanke.com/t/17291 小学应用题难度?大概画个图就能懂,把每个部分都标上号,算出a,b,c,d,e,f的部分,进行运算就行了. 不多解释了,直接上代码 #include<iostream> #include<cstdio> #include<algorithm> #include&l

URAL_1018 Binary Apple Tree 树形DP+背包

这个题目给定一棵树,以及树的每个树枝的苹果数量,要求在保留K个树枝的情况下最多能保留多少个苹果 一看就觉得是个树形DP,然后想出 dp[i][j]来表示第i个节点保留j个树枝的最大苹果数,但是在树形过程中,有点难表示转移 后来看了下大神的做法才知道其实可以用背包来模拟 树枝的去留,其实真的是个背包诶,每个子树枝就相当于物品,他占用了多少树枝量,带来多少的收益,就是用背包嘛,于是用树形DP+背包就可以做了 #include <iostream> #include <cstdio> #