首页 > 其他 > 详细

CodeForces 1324F. Maximum White Subtree【换根DP】

时间:2020-03-13 10:54:25      阅读:78      评论:0      收藏:0      [点我收藏+]

传送门

题意

给一颗树,每个节点有 \(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;
}

CodeForces 1324F. Maximum White Subtree【换根DP】

原文:https://www.cnblogs.com/BakaCirno/p/12484415.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!