Codeforces Round #551 (Div. 2) D. Serval and Rooted Tree 树形dp

48 篇文章 0 订阅
32 篇文章 0 订阅

D. Serval and Rooted Tree

题意:含有 n n n个节点,并且以 1 1 1为根节点的树的每个节点都有一个操作,用 01 01 01表示,如果为 1 1 1,那么就取这个节点的孩子中的最大值,否则取孩子的最小值。问,如何安排可以使得根节点 1 1 1的值最大。注意如果叶节点有 k k k个,那么取值必须是 1 → k 1\rightarrow k 1k

题解:听了某位苣苣的方程解释之后,立刻感觉理解了方程! d p i dp_i dpi表示以 i i i为根的子树与多少个叶子节点有关。那么对于操作值为 1 1 1的节点,它所对应的子树 d p u = m i n { d p v } dp_u = min\{dp_v \} dpu=min{dpv};对于操作值为 0 0 0的节点,它所对应的子树就是 d p u = ∑ v { u } d p v dp_u = \sum_v^{\{u\}}{dp_v} dpu=v{u}dpv。最后答案就是叶子节点个数加一再减去根节点与叶子节点相关的数量,即 l e a f + 1 − d p 1 leaf + 1 - dp_1 leaf+1dp1

代码

#include<bits/stdc++.h>

#define DEBUG(x) std::cerr << #x << '=' << x << std::endl

using namespace std;
const int N = 3E5+10;
vector<int> E[N];
int dp[N], a[N], leaf, n;

void dfs(int u)
{
	if(E[u].size() == 0) {
		dp[u] = 1;
		leaf++;
		return;
	}
	dp[u] = a[u] ? n : 0;
	for(const auto & v : E[u]) {
		dfs(v);
		if(a[u]) {
			dp[u] = min(dp[u],dp[v]);
		}else{
			dp[u] += dp[v];
		}
	}
}

int main()
{
#ifndef ONLINE_JUDGE
    freopen("input.in","r",stdin);
#endif
    ios::sync_with_stdio(false); cin.tie(0);
	int x;
	cin >> n;
	for(int i = 1; i <= n; ++i) {
		cin >> a[i];
	}
	for(int i = 2; i <= n; ++i) {
		cin >> x;
		E[x].emplace_back(i);
	}
	dfs(1);
	cout << leaf + 1 - dp[1] << endl;
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值