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


    题目链接
    题意:给你一个有根树,假设有k个叶子节点,你可以给每个叶子节点编个号,要求编号不重复且在1-k以内。然后根据节点的max,minmax,min信息更新节点的值,要求根节点的值最大。
    解法:考虑树形dp,若当前节点是nownow,我们可以假设编号最大的一些数分布在当前节点的子节点中,显然,若当前节点为叶子节点,那么这个这个编号就是最大的。然后往上回溯,假设当前节点取得是maxmax,那么就从子节点中取最大的数为当前节点的答案,如果取得是minmin的话,就要把子节点需要的叶子节点加起来,比如,一共有k个叶子,当前节点为nownow,子节点的答案分别为x1,x2...xm{x_1,x_2...x_m},那么当前节点的答案就应该是sumi=1mxi+1sum_{总的叶子数}-sum_{i=1}^mx_i+1,答案直接输入根节点的答案即可

    #include<bits/stdc++.h>
    
    #define LL long long
    #define fi first
    #define se second
    #define mp make_pair
    #define pb push_back
    
    using namespace std;
    
    LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
    LL lcm(LL a,LL b){return a/gcd(a,b)*b;}
    LL powmod(LL a,LL b,LL MOD){LL ans=1;while(b){if(b%2)ans=ans*a%MOD;a=a*a%MOD;b/=2;}return ans;}
    const int N = 3e5 +11;
    int n,a[N],f[N],cnt,dp[N];
    vector<int>v[N];
    int su[N];
    void get(int now){
    	if(!v[now].size()){su[now]=1;return ;}
    	int sum=0;
    	for(int k:v[now]){
    		get(k);
    		sum+=su[k];
    	}
    	su[now]=sum;
    	return ;
    }
    void dfs(int now){
    	if(!v[now].size()){dp[now]=cnt;return ;}
    	if(a[now]){
    		int ans=0;
    		for(int k:v[now]){
    			dfs(k);
    			ans=max(ans,dp[k]);
    		}
    		 dp[now]=ans;return;
    	}else{
    		int ans=0;
    		for(int k:v[now]){
    			dfs(k);
    			ans+=cnt-dp[k]+1;
    		}
    		dp[now]=cnt-ans+1;return ;
    	}
    }
    int main(){
    	ios::sync_with_stdio(false);
    	cin>>n;
    	for(int i=1;i<=n;i++)cin>>a[i];
    	for(int i=2;i<=n;i++){cin>>f[i],v[f[i]].pb(i);}
    	for(int i=1;i<=n;i++)cnt+=!v[i].size();
    	dfs(1);
    	cout<<dp[1];
    	return 0;
    }
    
  • 相关阅读:
    用ruby抓取网页
    [转] 从项目管理角度看敏捷开发
    ruby学习笔记(9)
    [转] 从项目管理角度看敏捷开发
    ruby学习笔记(8)
    ruby学习笔记(7)
    [转] 什么是敏捷开发
    netbeans tomcat
    maven
    jersey
  • 原文地址:https://www.cnblogs.com/pubgoso/p/10759700.html
Copyright © 2020-2023  润新知