Codeforces 461B - Appleman and Tree 树状DP
一棵树上有K个黑色节点,剩余节点都为白色,将其划分成K个子树,使得每棵树上都仅仅有1个黑色节点,共同拥有多少种划分方案。
个人感觉这题比較难。
如果dp(i,0..1)代表的是以i为根节点的子树种有0..1个黑色节点的划分方案数。
当节点i为白色时。对于它的每一个孩子的节点处理:
求dp(i, 0)时有:
1,将该节点与孩子节点相连,但要保证孩子节点所在的子树种没有黑色节点;
2,将该节点不与该孩子节点相连。则该孩子节点要保证所在子树种有黑色节点;
即dp(i, 0) = π(dp(j,0 ) + dp(j, 1)) 。当中j为i的孩子节点
求dp(i,1)时有:
将该节点与当中每一个孩子节点中的一个相连,而且保证该孩子节点所在子树中有1个黑色节点(所以共同拥有K种情况,K为该节点的孩子数)。而且对于剩下的节点能够选择连也能够选择不连。假设连接。则保证该子节点所在子树中没有黑色,假设不连。则要保证有黑色。所以对于剩下的每一个
子节点的处理方案书有dp(j,0) + dp(j,1)个。然后将每一个孩子处理的方案书相乘就可以,最后将全部的方案相加就可以。
当节点i为黑色的时候,求dp(i, 0) 肯定是0;
求dp(i, 1)时对于i的每一个子节点也是有两种选择,连或者不连,假设连接。则保证该子节点所在子树中没有黑色,假设不连,则要保证有黑色,即对于每一个子节点的处理数共同拥有
dp(j, 0) + dp(j, 1)个,然后将每一个孩子处理的方案数相乘。
终于dp(0,1)即为答案。这里如果0节点为根节点。
过程中能够加个小小的优化,当一个子节点所在的整棵子树中若没有黑色节点,那么该节点肯定与其父节点相连,所以计算时能够不考虑该节点。
#include <stdlib.h>
#include <stdio.h>
#include <algorithm>
#include <vector> using namespace std;
//int values[500001];
//long long sums[500001];
#define MODVALUE 1000000007
#define MOD(x) if((x) > MODVALUE) x %= MODVALUE; struct Edge
{
int to;
int i;
int totalcolor;
Edge()
{
totalcolor = 0;
}
}; int compp(const void* a1, const void* a2)
{
return *((int*)a2) - *((int*)a1);
} vector<Edge> G[100001];
int Color[100001];
long long res[100001][2];
//int TMP[100001];
bool Visited[100001]; void AddEdge(int from, int to)
{
Edge edge;
edge.to = to; edge.i = G[to].size();
G[from].push_back(edge);
edge.to = from; edge.i = G[from].size() - 1;
G[to].push_back(edge); } int CountColor(int node)
{
Visited[node] = true;
int count = 0;
if (Color[node])
{
count = 1;
}
for (int i = 0; i < G[node].size();i++)
{
Edge& edge = G[node][i];
if (!Visited[edge.to])
{
edge.totalcolor = CountColor(edge.to);
count += edge.totalcolor;
} }
return count;
} void GetAns(int node)
{
Visited[node] = true;
long long ans = 1;
int countofcolor = 0;
vector<int> TMP;
for (int i = 0; i < G[node].size(); i++)
{
Edge& edge = G[node][i];
if (Visited[edge.to])
{
continue;
}
//TMP[countofcolor++] = i;
GetAns(edge.to);
if (edge.totalcolor)
{
TMP.push_back(i);
countofcolor++;
//TMP[countofcolor++] = i;
}
}
res[node][0] = 0;
res[node][1] = 0; long long tmp1 = 1;
long long tmp0 = 1;
if (!Color[node])
{
tmp1 = 0;
}
for (int i = 0; i < countofcolor; i++)
{ if (Color[node])
{
Edge& edge = G[node][TMP[i]];
tmp1 *= (res[edge.to][1] + res[edge.to][0]);
MOD(tmp1);
tmp0 = 0;
}
else
{
Edge& edge1 = G[node][TMP[i]];
tmp0 *= (res[edge1.to][1] + res[edge1.to][0]);
MOD(tmp0);
long long tmp3 = 1;
for (int j = 0; j < countofcolor; j++)
{
Edge& edge = G[node][TMP[j]];
if (i == j)
{
tmp3 *= res[edge.to][1];
MOD(tmp3);
}
else
{
tmp3 *= (res[edge.to][1] + res[edge.to][0]);
MOD(tmp3);
} }
tmp1 += tmp3; } if (i == countofcolor - 1)
{
res[node][0] += tmp0;
res[node][1] += tmp1;
MOD(res[node][0]);
MOD(res[node][1]);
} }
if (countofcolor == 0)
{
res[node][0] = Color[node] ? 0 : 1;
res[node][1] = Color[node] ? 1 : 0;
}
} int main()
{
#ifdef _DEBUG
freopen("e:\\in.txt", "r", stdin);
#endif // _DEBUG
int n;
scanf("%d", &n);
for (int i = 0; i < n - 1; i++)
{
int value;
scanf("%d", &value);
AddEdge(i + 1, value);
}
for (int i = 0; i < n; i++)
{
int value;
scanf("%d", &value);
Color[i] = value;
}
memset(Visited, 0, sizeof(Visited));
CountColor(0);
memset(Visited, 0, sizeof(Visited));
GetAns(0);
printf("%I64d\n", res[0][1]);
return 0;
}
Codeforces 461B - Appleman and Tree 树状DP的更多相关文章
- Codeforces 461B Appleman and Tree(木dp)
题目链接:Codeforces 461B Appleman and Tree 题目大意:一棵树,以0节点为根节点,给定每一个节点的父亲节点,以及每一个点的颜色(0表示白色,1表示黑色),切断这棵树的k ...
- poj2486--Apple Tree(树状dp)
Apple Tree Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 7789 Accepted: 2606 Descri ...
- Codeforces 461B. Appleman and Tree[树形DP 方案数]
B. Appleman and Tree time limit per test 2 seconds memory limit per test 256 megabytes input standar ...
- Codeforces 461B Appleman and Tree
http://codeforces.com/problemset/problem/461/B 思路:dp,dp[i][0]代表这个联通块没有黑点的方案数,dp[i][1]代表有一个黑点的方案数 转移: ...
- CodeForces - 396C On Changing Tree(树状数组)
题目大意 给定一棵以1为根的树,初始时所有点为0 给出树的方式是从节点2开始给出每一个点的父亲 然后是 $m$ 次操作,分为两种 $1 v,k,x$ 表示在以v为根的子树中的每一个点上添加 $x-i* ...
- Codeforces 461B Appleman and Tree:Tree dp
题目链接:http://codeforces.com/problemset/problem/461/B 题意: 给你一棵树(编号从0到n-1,0为根节点),每个节点有黑白两种颜色,其中黑色节点有k+1 ...
- POJ 2486 Apple Tree [树状DP]
题目:一棵树,每个结点上都有一些苹果,且相邻两个结点间的距离为1.一个人从根节点(编号为1)开始走,一共可以走k步,问最多可以吃多少苹果. 思路:这里给出数组的定义: dp[0][x][j] 为从结点 ...
- CodeForces 160D - Distance in Tree 树型DP
题目给了512MB的空间....用dp[k][i]代表以k为起点...往下面走(走直的不打岔)i步能有多少方案....在更新dp[k][i]过程中同时统计答案.. Program: #include& ...
- Codeforces 161D Distance in Tree(树型DP)
题目链接 Distance in Tree $k <= 500$ 这个条件十分重要. 设$f[i][j]$为以$i$为子树,所有后代中相对深度为$j$的结点个数. 状态转移的时候,一个结点的信息 ...
随机推荐
- 用Delphi进行word开发
使用以CreateOleObjects方式调用Word 实际上还是Ole,但是这种方式能够真正做到完全控制Word文件,能够使用Word的所有属性,包括自己编写的VBA宏代码.------------ ...
- 升级版:深入浅出Hadoop实战开发(云存储、MapReduce、HBase实战微博、Hive应用、Storm应用)
Hadoop是一个分布式系统基础架构,由Apache基金会开发.用户可以在不了解分布式底层细节的情况下,开发分布式程序.充分利用集群的威力高速运算和存储.Hadoop实现了一个分布式文件系 ...
- MySQL filesort优化案例一则
今天遇到一个filesort优化的案例,感觉不错,分享出来. MySQL中filesort是什么意思?官方手册定义: MySQL must do an extra pass to find out h ...
- Effective C++_笔记_条款02_尽量以const、enum、inline替换#define
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) 这个条款或许改为“宁可以编译器替换预处理器”比较好,因为或许#d ...
- Android SDK 环境变量配置(Windows)
Android 开发需要进行adb的配置, 这里使用的是 adt-bundle-windows-x86_64-20140321, 里面捆绑的有 eclipse ,不需要再进行 其他的配置,直接下载解压 ...
- Mysql 5.1升级为mysql 5.6遇到的问题及解决方式
yum是不可行的.因为yum源没更新,我已经使用了163网易的源,但是还是不行.最新版仍然不是5.6.没办法,mysql分区是5.5之后的功能,要使用分区功能,就必须升级.. 去官网下载地址:http ...
- 【Cocos2d-X游戏实战开发】捕鱼达人之开发前准备工作(一)
本系列学习教程使用的是cocos2d-x-2.1.4(最新版为cocos2d-x-2.1.5) 博主发现前两个系列的学习教程被严重抄袭,在这里呼吁大家请尊重开发者的劳动成果, 转载的时候请务必注明出处 ...
- 分分钟教会你使用HTML写Web页面
在学习怎样使用HTML编写网页之前,我们必须先搞清楚什么是HTML?当然了不是系统的给大家介绍HTML的前世今生,假设对其身世感兴趣的小伙伴能够去问度娘,她会给你想要的答案. 所谓HTML,就是我们常 ...
- [Win]进程间通信——邮槽Mailslot
进程间通信 进程的地址空间是私有的.出于安全性的目的,如果一个进程不具有特殊的权限,是无法访问另外一个进程的内存空间的,也无法知道内存中保存的数据的意义.但是在一些具体的应用情况下需要多个进行相互配合 ...
- Linux Shell常用技巧(二) grep
七. grep家族: 1. grep退出状态: 0: 表示成功: 1: 表示在所提供的文件无法找到匹配的pattern: 2: 表示参数中提供的文件不存在. 见如 ...