专栏文章
题解:CF1153D Serval and Rooted Tree
CF1153D题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqgae1l
- 此快照首次捕获于
- 2025/12/04 04:19 3 个月前
- 此快照最后确认于
- 2025/12/04 04:19 3 个月前
题目传送门
首先,我们先考虑二分一个 ,检查“根结点的最大值会不会 ”。那么对于叶子结点 的值,就可以化为 和 ,表示这个值是不是 。要使根结点的值尽可能大,就要使 的使用次数尽可能小,所以设 表示以 为根的子树中叶子结点最少使用多少个 ,才能使 这个点的值为 。先考虑 点的操作为取 : 的儿子一定都要是 ,所以 (其中 为 的儿子)。再考虑 点的操作为取 : 的儿子只要有一个为 即可,所以 (其中 为 的儿子)。列出转移方程,我们发现貌似没有用到 ,所以把二分去掉,答案就为 。
code:
CPP首先,我们先考虑二分一个 ,检查“根结点的最大值会不会 ”。那么对于叶子结点 的值,就可以化为 和 ,表示这个值是不是 。要使根结点的值尽可能大,就要使 的使用次数尽可能小,所以设 表示以 为根的子树中叶子结点最少使用多少个 ,才能使 这个点的值为 。先考虑 点的操作为取 : 的儿子一定都要是 ,所以 (其中 为 的儿子)。再考虑 点的操作为取 : 的儿子只要有一个为 即可,所以 (其中 为 的儿子)。列出转移方程,我们发现貌似没有用到 ,所以把二分去掉,答案就为 。
code:
#include<bits/stdc++.h>
using namespace std;
const int N=3e5+5;
int n,m,opt[N],dp[N];
vector<int> e[N];
void dfs(int x)
{
if(e[x].size()==0)
{
dp[x]=1;
return ;
}
int ans1=1e9,ans2=0;
for(int i=0;i<e[x].size();i++)
{
int y=e[x][i];
dfs(y);
ans1=min(ans1,dp[y]),ans2+=dp[y];
}
if(opt[x]) dp[x]=ans1;
else dp[x]=ans2;
return ;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%d",opt+i);
for(int i=2;i<=n;i++)
{
int x;
scanf("%d",&x);
e[x].push_back(i);
}
for(int i=2;i<=n;i++) m+=(e[i].size()==0);
dfs(1);
cout<<m-dp[1]+1;
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...