zoukankan      html  css  js  c++  java
  • CodeForces 1324F. Maximum White Subtree【换根DP】

    传送门

    题意

    给一颗树,每个节点有 (1)(-1) 两种权值,问对于每一个点,包含它的联通块权值最大是多少。

    题解

    第一次写换根DP,其实并不难。相反 E 题记忆化搜索没想出来是真的煞笔。
    就是一个最板的换根DP,先把 (1) 视作根节点,算出每个点的最大子树。
    然后再进行树形DP,每次向儿子转移时将自己、父亲、其他儿子的最大总权传给儿子。

    代码

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include <queue>
    using namespace std;
    typedef long long LL;
    const int N=2e5+10;
    const int M=1e6+10;
    int n,a[N],maxs[N],ans[N];
    vector<int> g[N];
    
    void dfs1(int u,int fa){
    	maxs[u]=a[u];
    	for(int v:g[u]){
    		if(v==fa) continue;
    		dfs1(v,u);
    		if(maxs[v]>0) maxs[u]+=maxs[v];
    	}
    }
    
    void dfs2(int u,int fa,int w){
    	if(w<0) w=0;
    	ans[u]=maxs[u]+w;
    	for(int v:g[u]){
    		if(v==fa) continue;
    		if(maxs[v]>0) dfs2(v,u,w+maxs[u]-maxs[v]);
    		else dfs2(v,u,w+maxs[u]);
    	}
    }
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<=n;i++){
    		scanf("%d",&a[i]);
    		if(a[i]==0) a[i]=-1;
    	}
    	for(int i=1,u,v;i<n;i++){
    		scanf("%d%d",&u,&v);
    		g[u].push_back(v);
    		g[v].push_back(u);
    	}
    	dfs1(1,0);
    	dfs2(1,0,0);
    	for(int i=1;i<=n;i++) printf("%d ",ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    机器学习之路--Python
    机器学习之路--Pandas
    机器学习之路--seaborn
    机器学习之路--Matplotlib
    囫囵吞枣——SVG
    囫囵吞枣——XML
    囫囵吞枣——Jquery 笔记
    囫囵吞枣——JavaScript
    囫囵吞枣——CSS3
    囫囵吞枣——CSS笔记
  • 原文地址:https://www.cnblogs.com/BakaCirno/p/12484415.html
Copyright © 2011-2022 走看看