题意:给出一棵树,最开始所有节点都是白的。进行一些操作来计算树的价值。每次操作可以选一个节点,给价值加上包括这个结点在内的白色连通块大小。然后把这个结点染成黑色。除第一次操作外,每次只能选择与黑色结点直接相连的白色结点。求这棵树的最大价值。
解:分析一下就是,每次选一个结点,给价值加上以它为根的子树的大小。选一个结点作为根节点,树的价值就是所有子树大小之和。然后进行一些换根操作。已知一个结点的dp值为它所有结点dp值加上它子树大小,那么把它变成它子节点子树时,就要减去子节点dp值,减去目前子树大小,加上其余子节点子树大小。对子节点处理同理。
直接在昨天代码上改就可以,很快乐(
代码:
#include <bits/stdc++.h> using namespace std; #define maxx 200005 #define maxn 25 #define maxm 205 #define ll long long #define inf 1000000009 #define mod 2520 struct edge{ int u,v,w,next; }e[maxx*2]; int head[maxx]={0},cnt=0; void add(int u,int v){ e[++cnt].u=u;e[cnt].v=v;e[cnt].next=head[u];head[u]=cnt; } int n; ll ans=0; ll dp[maxx]={0}; ll son[maxx]={0}; void dfs1(int now,int fa){ son[now]=1; for(int i=head[now];i;i=e[i].next){ int to=e[i].v; if(to==fa) continue; dfs1(to,now); dp[now]+=dp[to]; son[now]+=son[to]; } dp[now]+=son[now]; } void dfs2(int now,int fa){ ans=max(ans,dp[now]); for(int i=head[now];i;i=e[i].next){ int to=e[i].v; if(to==fa) continue; dp[now]-=son[to]; dp[now]-=dp[to]; son[now]-=son[to]; dp[to]+=dp[now]; dp[to]+=son[now]; son[to]+=son[now]; dfs2(to,now); son[to]-=son[now]; dp[to]-=son[now]; dp[to]-=dp[now]; son[now]+=son[to]; dp[now]+=dp[to]; dp[now]+=son[to]; } } signed main() { scanf("%d",&n); for(int i=1;i<=n-1;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y); add(y,x); } dfs1(1,0); dfs2(1,0); printf("%lld\n",ans); return 0; }