1.CF1324F Maximum White Subtree
给定一棵 n n n 个节点无根树,每个节点 u u u 有一个颜色 a u a_u au,若 a u a_u au 为 0 0 0 则 u u u 是黑点,若 a u a_u au 为 1 1 1 则 u u u 是白点。
- 对于每个节点 u u u,选出一个包含 u u u 的连通子图,设子图中白点个数为 c n t 1 cnt_1 cnt1,黑点个数为 c n t 2 cnt_2 cnt2,请最大化 c n t 1 − c n t 2 cnt_1 - cnt_2 cnt1−cnt2。并输出这个值。
- 1 ≤ n ≤ 2 × 1 0 5 1 \leq n \leq 2 \times 10^5 1≤n≤2×105, 0 ≤ a u ≤ 1 0 \leq a_u \leq 1 0≤au≤1。
思路:
换根dp
第一次dfs,先用1做根预处理出每个点的子树中最大的cnt1-cnt2(自底向上)
第二次dfs,对于每一个子树
若该子树的size>0,则有两种选择,一种是只选择这棵子树,二是选择整棵树
若该子树size<0,可以选择这棵子树或者选择整棵树,因为父亲树是不包括它的,所以要父亲树加上这棵子树
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,k,t,cnt,tt;
int size[maxn];
vector<int>e[maxn];
void dfs1(int u,int fa){
for(auto v:e[u]){
if(v==fa)continue;
dfs1(v,u);
if(size[v]>0)size[u]+=size[v];
}
}
void dfs2(int u,int fa){
for(auto v:e[u]){
if(v==fa)continue;
if(size[v]>0){
size[v]=max(size[v],size[u]);
}
else{
size[v]=max(size[v],size[u]+size[v]);
}
dfs2(v,u);
}
}
int main(){
cin>>n;
int flag=0;
for(int i=1;i<=n;i++){
cin>>size[i];
if(!size[i])size[i]=-1;
}
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs1(1,1);
dfs2(1,1);
for(int i=1;i<=n;i++){
printf("%d ",size[i]);
}
}
咕了