cf 551 div2 D——Serval and Rooted Tree (树形DP)

题目链接:http://codeforces.com/contest/1153/problem/D

D. Serval and Rooted Tree

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

Now Serval is a junior high school student in Japari Middle School, and he is still thrilled on math as before.

As a talented boy in mathematics, he likes to play with numbers. This time, he wants to play with numbers on a rooted tree.

A tree is a connected graph without cycles. A rooted tree has a special vertex called the root. A parent of a node vv is the last different from vv vertex on the path from the root to the vertex vv. Children of vertex vv are all nodes for which vv is the parent. A vertex is a leaf if it has no children.

The rooted tree Serval owns has nn nodes, node 11 is the root. Serval will write some numbers into all nodes of the tree. However, there are some restrictions. Each of the nodes except leaves has an operation maxmax or minmin written in it, indicating that the number in this node should be equal to the maximum or minimum of all the numbers in its sons, respectively.

Assume that there are kk leaves in the tree. Serval wants to put integers 1,2,…,k1,2,…,k to the kk leaves (each number should be used exactly once). He loves large numbers, so he wants to maximize the number in the root. As his best friend, can you help him?

Input

The first line contains an integer nn (2≤n≤3⋅1052≤n≤3⋅105), the size of the tree.

The second line contains nn integers, the ii-th of them represents the operation in the node ii. 00 represents minmin and 11 represents maxmax. If the node is a leaf, there is still a number of 00 or 11, but you can ignore it.

The third line contains n−1n−1 integers f2,f3,…,fnf2,f3,…,fn (1≤fi≤i−11≤fi≤i−1), where fifi represents the parent of the node ii.

Output

Output one integer — the maximum possible number in the root of the tree.

Examples

input

Copy

6
1 0 1 1 0 1
1 2 2 2 2

output

Copy

1

input

Copy

5
1 0 1 0 1
1 1 1 1

output

Copy

4

input

Copy

8
1 0 0 1 0 1 1 0
1 1 2 2 3 3 3

output

Copy

4

input

Copy

9
1 1 0 0 1 0 1 0 1
1 1 2 2 3 3 4 4

output

Copy

5

Note

Pictures below explain the examples. The numbers written in the middle of the nodes are their indices, and the numbers written on the top are the numbers written in the nodes.

In the first example, no matter how you arrange the numbers, the answer is 11.

In the second example, no matter how you arrange the numbers, the answer is 44.

In the third example, one of the best solution to achieve 44 is to arrange 44 and 55 to nodes 44 and 55.

In the fourth example, the best solution is to arrange 55 to node 55.

【题解】:(这我是真想不到还能这样DP,ORZ)

以dp[i]表示以i为根节点的子树,它达到最大值需要消耗的叶子节点的个数,那么点i能达到的最大值就是它的子树有的叶子节点数k-dp[i]+1,可以这么理解:dp[i]是为了叶子节点到达根节点需要消耗的节点个数,那么把这几个节点的编号置为最大,是不是就可以让根节点i达到最大值?

理解了为什么这么设之后,就可以写出转移方程。

(1)如果点i为max,那么它可以直接从子节点传递上来,需要消耗的叶子节点个数就是最小的dp[v],v为i的直接子节点;

(2)如果点i为min,那么我们就需要将叶子节点从小到大赋值,这时i的每个子节点都会被消耗,所以dp[u]=\sumdp[v]

代码如下:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;

const int maxn=3e5+10;
const int INF=0x3f3f3f3f;
int dp[maxn];//表示以i为根节点的子树,它达到最大值需要消耗的叶子数
int flag[maxn];//每个节点的标签为1或0
vector<int>G[maxn];
int cnt;

void dfs(int u){
	if(!G[u].size()){
		dp[u]=1;//叶子节点为1
		cnt++;
		return;
	}
	if(flag[u]){
		//最大值,只要让一个儿子最大,那么其他置为最小
		dp[u]=INF;
		for(int i=0;i<G[u].size();i++){
			int v=G[u][i];
			dfs(v);
			dp[u]=min(dp[u],dp[v]);
		}
	}
	else{
		//最小值,那么所有子节点都要消耗个数
		dp[u]=0;
		for(int i=0;i<G[u].size();i++){
			int v=G[u][i];
			dfs(v);
			dp[u]+=dp[v];
		}
	}
}
int main(){
	int n;
	while(scanf("%d",&n)!=EOF){
		for(int i=0;i<=n;i++)G[i].clear();
		cnt=0;
		for(int i=1;i<=n;i++){
			scanf("%d",&flag[i]);
		}
		for(int i=1;i<n;i++){
			int fa;
			scanf("%d",&fa);
			G[fa].push_back(i+1);
		}
		dfs(1);
		printf("%d\n",cnt-dp[1]+1);
	}
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值