E. Tree Painting
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given a tree (an undirected connected acyclic graph) consisting of n vertices. You are playing a game on this tree.
Initially all vertices are white. On the first turn of the game you choose one vertex and paint it black. Then on each turn you choose a white vertex adjacent (connected by an edge) to any black vertex and paint it black.
Each time when you choose a vertex (even during the first turn), you gain the number of points equal to the size of the connected component consisting only of white vertices that contains the chosen vertex. The game ends when all vertices are painted black.
Let’s see the following example:
Vertices 1 and 4 are painted black already. If you choose the vertex 2, you will gain 4 points for the connected component consisting of vertices 2,3,5 and 6. If you choose the vertex 9, you will gain 3 points for the connected component consisting of vertices 7,8 and 9.
Your task is to maximize the number of points you gain.
Input
The first line contains an integer n — the number of vertices in the tree (2≤n≤2⋅105).
Each of the next n−1 lines describes an edge of the tree. Edge i is denoted by two integers ui and vi, the indices of vertices it connects (1≤ui,vi≤n, ui≠vi).
It is guaranteed that the given edges form a tree.
Output
Print one integer — the maximum number of points you gain if you will play optimally.
Examples
inputCopy
9
1 2
2 3
2 5
2 6
1 4
4 9
9 7
9 8
outputCopy
36
inputCopy
5
1 2
1 3
2 4
2 5
outputCopy
14
Note
The first example tree is shown in the problem statement.
题意:给一棵树,起初每个顶点都是白色,第一轮你可以随意选择一个顶点染成黑色,以后每轮你可以选择已经染成黑色的顶点的相邻白色顶点染色,每轮得到的分数=从当前白色顶点出发,只经过白色顶点可以遍历到的白色顶点数(包括自己)(也就是所选白结点所在白色连通块的大小),求最大总价值
题解:很容易得到根为某个结点的结果,而当根从这个结点向相邻结点转移时只改变了这两个点的某些信息,所以可以很快进行换根后的结果转移,在转移过程更新答案即可
#include<bits/stdc++.h>
using namespace std;
#define debug(x) cout<<#x<<" is "<<x<<endl;
typedef long long ll;
const int maxn=2e5+5;
struct edge{
int fr;
int to;
int nex;
}e[maxn<<1];
ll cnt,ans,head[maxn],siz[maxn],dp[maxn];
void adde(int x,int y){
e[cnt].fr=x;
e[cnt].to=y;
e[cnt].nex=head[x];
head[x]=cnt++;
}
void caldp(int u,int f){
dp[u]=siz[u];
for(int i=head[u];i!=-1;i=e[i].nex){
int v=e[i].to;
if(v==f)continue;
caldp(v,u);
dp[u]+=dp[v];
}
}
void dfs(int u,int f){
ans=max(ans,dp[u]);
for(int i=head[u];i!=-1;i=e[i].nex){
int v=e[i].to;
if(v==f)continue;
dp[u]-=dp[v];
dp[u]-=siz[v];
siz[u]-=siz[v];
dp[v]+=dp[u];
dp[v]+=siz[u];
siz[v]+=siz[u];
dfs(v,u);
siz[v]-=siz[u];
dp[v]-=siz[u];
dp[v]-=dp[u];
siz[u]+=siz[v];
dp[u]+=siz[v];
dp[u]+=dp[v];
}
}
void calsiz(int u,int f){
siz[u]=1;
for(int i=head[u];i!=-1;i=e[i].nex){
int v=e[i].to;
if(v==f)continue;
calsiz(v,u);
siz[u]+=siz[v];
}
}
int main(){
int n;
scanf("%d",&n);
memset(head,-1,sizeof(head));
for(int i=1;i<n;i++){
int a,b;
scanf("%d%d",&a,&b);
adde(a,b);
adde(b,a);
}
calsiz(1,-1);
caldp(1,-1);
dfs(1,-1);
printf("%lld\n",ans);
return 0;
}