第一次补题AK,终于有场绿色的了
为了这个F题,这两天专门学习了树形DP
没做什么特别难的题,感觉套路都差不多,再多做几道加深加深印象
这道大体意思是每个点有黑或白色,为每个点找一个连通块,使这个连通块内 白色点的数目-黑色点的数目 最大
说实话就是树形DP模板稍一改就可以了
链式前向星存双向边,记得开双倍空间,小心re。。。别问我怎么知道的。。。。
代码:
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int MaxSize = 200005;
struct node
{
int to,next;
}q[3*MaxSize];
int a[MaxSize],head[MaxSize],cnt=1,d[MaxSize];
void add(int a,int b)
{
q[cnt].to=a;
q[cnt].next=head[b];
head[b]=cnt;
cnt++;
}
void dfs(int u,int f)
{
for(int i=head[u];i!=-1;i=q[i].next)
{
int v=q[i].to;
if(v==f)
{continue;}
dfs(v,u);
d[u]=max(d[u],d[v]+d[u]);
}
return ;
}
void dfs2(int u,int f)
{
if(u!=f)
{
if(d[u]>=0)
{d[u]=max(d[u],d[f]);}
else
{d[u]=max(d[u],d[u]+d[f]);}
}
for(int i=head[u];i!=-1;i=q[i].next)
{
int v=q[i].to;
if(v==f)
{continue;}
dfs2(q[i].to,u);
}
return;
}
int main()
{
memset(head,-1,sizeof(head));
int n,x,y;
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
if(a[i]==0)d[i]=-1;
else{d[i]=1;}
}
for(int i=1;i<=n-1;i++)
{
scanf("%d %d",&x,&y);
add(x,y);add(y,x);
}
dfs(1,1);
dfs2(1,1);
for(int i=1;i<=n;i++)
{
cout<<d[i]<<" ";
}
cout<<endl;
return 0;
}