CF263(D1)B 树形DP

【题意】:

给出一张无向图,图中每个点着有颜色(1或者0),问有多少种不同的切割方法,使切割后每一块区域恰有一个黑点。

【知识点】:

树形DP

【题解】:

dp方程声明如下

dp[u][0]:表示以跟节点为u的树,有多少种切割方法,使切成若干个区域后,u所在的区域为唯一一个没有黑点的区域。

dp[u][1]:表示以跟节点为u的树,有多少种切割方法,使切割后的每个区域(包括u所在的区域)恰有一个黑点。

那么当u点为黑点时

dp[u][0]=0。 dp[u][1]=若干个(dp[v][0] + dp[v][1])的乘积。

u为白色节点时

dp[u][0]=若干个(dp[v][0] + dp[v][1])的乘积。 dp[u][1]=若干个(dp[v][1]与其它子节点(dp[v][0] + dp[v][1])的乘积)的和。

叙述并不是很清楚,有待改进,因为自己思路也一直模模糊糊的。

【代码】:

 1 #include <map>
 2 #include <set>
 3 #include <cmath>
 4 #include <ctime>
 5 #include <queue>
 6 #include <stack>
 7 #include <cstdio>
 8 #include <string>
 9 #include <vector>
10 #include <cstring>
11 #include <sstream>
12 #include <iostream>
13 #include <algorithm>
14 #include <bitset>
15 #include <climits>
16 using namespace std;
17
18 #define wh while
19 #define inf (int)(~0u/2)
20 #define FOR(i, n) for(int i = 0; i < n; i++)
21 #define FOR1(i, n) for(int i = 1; i < n; i++)
22 #define FOR2(i, n) for(int i = 0; i <= n; i++)
23 #define REP(i,n) for(int i = 1; i <= n; i++)
24 #define FORI(it,n) for(typeof(n.begin()) it = n.begin(); it != n.end(); it++)
25 #define sf scanf
26 #define pf printf
27 #define frs first
28 #define sec second
29 #define psh push_back
30 #define mkp make_pair
31 #define PB(x) push_back(x)
32 #define MP(x, y) make_pair(x, y)
33 #define clr(abc,z) memset(abc,z,sizeof(abc))
34 #define lt(v) v << 1
35 #define rt(v) v << 1 | 1
36 //#define mid ((l + r) >> 1)
37 #define lson l, mid, v << 1
38 #define rson mid + 1, r, v << 1 | 1
39
40 #define fre freopen("1.txt", "r", stdin)
41
42 typedef long long LL;
43 typedef long double LD;
44
45 const int MOD = 1e9 + 7;
46
47 const int maxn = 1e5 + 100;
48 int dp[maxn][2];
49 int val[maxn];
50 vector<int> G[maxn];
51 int add(int a, int b){
52     return (a + b) % MOD;
53 }
54 int mul(int a, int b){
55     return a * (LL)b % MOD;
56 }
57 void dfs(int u){
58     dp[u][val[u]] = 1; dp[u][val[u] ^ 1] = 0;
59     FOR(i, (int)G[u].size()){
60         int v = G[u][i];
61         dfs(v);
62         int last0 = dp[u][0], last1 = dp[u][1];
63         dp[u][0] = mul(last0, add(dp[v][0], dp[v][1]));
64         dp[u][1] = add(mul(last0, dp[v][1]),
65             mul(last1, add(dp[v][0], dp[v][1])));
66     }
67 }
68
69 int main(){
70     int n;
71     wh(sf("%d", &n) != EOF){
72         FOR(i, n) G[i].clear();
73         FOR(i, n - 1){
74             int tmp; sf("%d", &tmp);
75             G[tmp].PB(i + 1);
76         }
77         FOR(i, n) sf("%d", &val[i]);
78         dfs(0);
79         pf("%d\n", dp[0][1]);
80     }
81 }

时间: 2024-08-24 17:38:22

CF263(D1)B 树形DP的相关文章

hdu5293 Tree chain problem 树形dp+线段树

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5293 在一棵树中,给出若干条链和链的权值.求选取不相交的链使得权值和最大. 比赛的时候以为是树链剖分就果断没去想,事实上是没思路. 看了题解,原来是树形dp.话说多校第一场树形dp还真多. . .. 维护d[i],表示以i为根节点的子树的最优答案. sum[i]表示i的儿子节点(仅仅能是儿子节点)的d值和. 那么答案就是d[root]. 怎样更新d值 d[i] = max(sum[i] , w[p]+s

HDU 4008 Parent and son LCA+树形dp

题意: 给定case数 给定n个点的树,m个询问 下面n-1行给出树边 m个询问 x y 问:以x为根,y子树下 y的最小点标的儿子节点 和子孙节点 思路: 用son[u][0] 表示u的最小儿子 son[u][2] 表示u的次小儿子 son[u][1] 表示u的最小子孙 若lca(x,y)  !=y  则就是上述的答案 若lca(x,y) == y 1.y != 1 那么最小儿子就是除了x外的节点,且此时father[y] 也是y的儿子节点, 而最小的子孙节点就是1 2.y==1 那么特殊处理

【BZOJ-3572】世界树 虚树 + 树形DP

3572: [Hnoi2014]世界树 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 1084  Solved: 611[Submit][Status][Discuss] Description 世界树是一棵无比巨大的树,它伸出的枝干构成了整个世界.在这里,生存着各种各样的种族和生灵,他们共同信奉着绝对公正公平的女神艾莉森,在他们的信条里,公平是使世界树能够生生不息.持续运转的根本基石.世界树的形态可以用一个数学模型来描述:世界树中有n个种族,种

HDU 4274 Spy&#39;s Work (树形DP,模拟)

题意: 给定一棵树,每个节点代表一个员工,节点编号小的级别就小,那么点1就是boss了.接下来给出对m个点的限制,有3种符号分别是op=“大于/小于/等于”,表示以第i个点为根的子树所有人的工资之和 大于/小于/等于 x,要求判断m个限制是否冲突了.注意每个员工的工资下限是1,而无上限.ps:可能出现对同个点多个限制,注意取交集. 思路: 很水的题嘛,想复杂了.注意限制是针对整棵子树的!所以我们只需要算出这棵子树的范围,再判断是否和所给的限制有冲突,如果没有冲突的话还得取“所给限制”与“计算出的

美团2017年CodeM大赛-初赛B轮 黑白树 (树形dp)

大意: 给定树, 初始每个点全为白色, 点$i$有权值$k_i$, 表示选择$i$后, 所有距离$i$小于$k_i$的祖先(包括i)会变为黑色, 求最少选多少个点能使所有点变为黑色. 链上情况的话, 直接从链头开始做一次线性dp就行了, 但是显然不能拓展到树上情况. 正解是从叶子往上贪心划分, 若当前点$x$为白色, 则从$x$子树内选择一个$y$, 满足$k[y]-dis(x,y)$最大, 这个显然可以用树形dp在O(n)时间求出. #include <iostream> #include

[Bzoj 2427] [HAOI2010] 软件安装 tarjan缩点+树形DP

题目描述 现在我们的手头有N个软件,对于一个软件i,它要占用Wi的磁盘空间,它的价值为Vi.我们希望从中选择一 些软件安装到一台磁盘容量为M计算机上,使得这些软件的价值尽可能大(即Vi的和最大). 但是现在有个问题:软件之间存在依赖关系,即软件i只有在安装了软件j(包括软件j的直接或间接依赖)的情况下才能正确工作(软件i依赖软件j).幸运的 是,一个软件最多依赖另外一个软件.如果一个软件不能正常工作,那么它能够发挥的作用为0. 我们现在知道了软件之间的依赖关系:软件i依赖软件Di.现在请你设计出

【模板】树形DP求直径和负直径

注意,若负直径指广义的直径--可以缩成一个点,树形DP无法正确求出,需要将初值设为0(若大于0则不更新) void dfs(int u,int fa,ll &d1,ll &d2){ f[u]=f2[u]=0; for(int i=head[u];i+1;i=e[i].nxt){ if(cut[i]) continue; int v=e[i].v,w=e[i].w; if(v==fa) continue; dfs(v,u,d1,d2); d1=max(d1,f[v]+w+f[u]); f[u

HDU-2196 Computer (树形DP)

最近在看树形DP,这题应该是树形DP的经典题了,写完以后还是有点感觉的.之后看了discuss可以用树分治来做,以后再试一试. 题目大意 找到带权树上离每个点的最远点.︿( ̄︶ ̄)︿ 题解: 对于每一个点的最远点,就是以这个点为根到所有叶子节点的最长距离.但是如果确定根的话,除了根节点外,只能找到每个节点(度数-1)个子树的最大值,剩下一个子树是该节点当前的父亲节点. 所以当前节点的最远点在当前节点子树的所有叶子节点以及父亲节点的最远点上(当父亲节点的最远点不在当前节点的子树上时), 如果父亲节

UVA-01220 Party at Hali-Bula (树形DP+map)

题目链接:https://vjudge.net/problem/UVA-1220 思路: 树形DP模板题,求最大人数很简单,难点在于如何判断最大人数的名单是否有不同的情况: 解决方法是用一个数组f[manx][2]记录该节点是否出场的情况,为真时代表有多种情况; 具体讨论: 当父节点的值加上某个子节点的值时,他的f的情况也和该子节点一样: 当某个节点dp(i, 0) == dp(i, 1), 则该节点以及它的父节点也一定有多种情况(父节点必定取其中之一). Code: 1 #include<bi