Codeforces 1324 F. Maximum White Subtree(换根dp)

题目链接
题目大意:
仔细读题,可以发现不是传统的子树,只是一个连通子图,给定一棵树的图,每个节点为“1”或“0”,对每个点输出包含这个点的连通子图的的1的个数-0的个数最大值。

解题思路:
第一遍dfs随便找一个点作为树根,然后dp1[u]表示包含u及其子树范围的连通子图的最大值。
第二遍dfs进行转移。
1、当前子树(包含自己)如果是正的,直接取,否则就只取当前点。
2、除了当前子树以外(必须包含父节点)如果是正的也要取,负的就不取。

解题代码:

#include<bits/stdc++.h>
using namespace std;
mt19937 rng_32(chrono::steady_clock::now().time_since_epoch().count());
typedef long long ll;
const int maxn=2e5+10;
struct E{
    int to,nxt;
}e[maxn*2];
int head[maxn],tot=0;
void adde(int u,int v)
{
    tot++;
    e[tot].nxt=head[u];
    e[tot].to=v;
    head[u]=tot;
}
int a[maxn];
int dp1[maxn],dp2[maxn];
void dfs1(int u,int fa)
{
    if (a[u]==0)
    dp1[u]=-1;
    else
    dp1[u]=1;
    for (int i=head[u];i;i=e[i].nxt)
    {
        int to=e[i].to;
        if (to==fa)
        continue;
        dfs1(to,u);
        if (dp1[to]>0)
        dp1[u]+=dp1[to];
    }
}
void dfs2(int u,int fa)
{
    int tmp=(a[u]==0? -1:1);
    dp2[u]=max(tmp,dp1[u])+max(0,dp2[fa]-max(0,dp1[u]));
    for (int i=head[u];i;i=e[i].nxt)
    {
        if (e[i].to==fa)
        continue;
        dfs2(e[i].to,u);
    }
}
int main()
{
    int n;
    scanf("%d",&n);
    for (int i=1;i<=n;i++)
    scanf("%d",&a[i]);
    int t1,t2;
    for (int i=1;i<n;i++)
    {
        scanf("%d%d",&t1,&t2);
        adde(t1,t2);
        adde(t2,t1);
    }
    dfs1(1,1);
    dfs2(1,1);
    for (int i=1;i<=n;i++)
    cout<<dp2[i]<<" ";
    return 0;
}
发布了12 篇原创文章 · 获赞 1 · 访问量 327

猜你喜欢

转载自blog.csdn.net/qq_41818939/article/details/104839094