记忆化搜索 (会TLE
#include<bits/stdc++.h>//TLE
#define MAXN 200010
using namespace std;
typedef pair<int ,int> P;
vector <int> a[MAXN], aa;
map <P, int> paint, dp;
void add_edge(int u, int v){
a[u].push_back(v);
a[v].push_back(u);
}
int Paint(int now, int fa){
P p = make_pair(fa, now);
if(paint[p]) return paint[p];
for(int i = 0; i < a[now].size(); i++){
int u = a[now][i];
if(u == fa) continue;
paint[p] += Paint(u, now);
}
if(!paint[p]) aa.push_back(now);
return ++paint[p];
}
int dfs(int now, int fa){
P p = make_pair(fa, now);
if(dp[p]) return dp[p];
for(int i = 0; i < a[now].size(); i++){
int u = a[now][i];
if(u == fa) continue;
dp[p] += dfs(u, now);
}
dp[p] += paint[p];
return dp[p];
}
int main(){
int n, u, v, ans = 0;
scanf("%d", &n);
for(int i = 1; i < n; i++){
scanf("%d%d", &u, &v);
add_edge(u, v);
}
for(int i = 1; i <= n; i++) Paint(i, -1);
for(int i = 0; i < aa.size(); i++) ans = max(ans, dfs(aa[i], -1));
printf("%d", ans);
return 0;
}
正解:二次扫描换根法
参考博客https://blog.csdn.net/baiyifeifei/article/details/94413699
#include<bits/stdc++.h>
#define ll long long
#define MAXN 200010
using namespace std;
ll sz[MAXN], val[MAXN], n;
vector <int> a[MAXN];
void add_edge(int u, int v){
a[u].push_back(v);
a[v].push_back(u);
}
void dfs(int now, int fa){
sz[now] = 1;
for(int i = 0; i < a[now].size(); i++){
int u = a[now][i];
if(u == fa) continue;
dfs(u, now);
sz[now] += sz[u];
val[now] += val[u];
}val[now] += sz[now];
}
void dfs2(int now, int fa){
if(fa) val[now] += val[fa] - val[now] + n - sz[now] - sz[now];//!
for(int i = 0; i < a[now].size(); i++)
if(fa != a[now][i]) dfs2(a[now][i], now);
}
int main(){
ll u, v, ans = 0;
scanf("%d", &n);
for(int i = 1; i < n; i++){
scanf("%d%d", &u, &v);
add_edge(u, v);
}
dfs(1, 0); dfs2(1, 0);
for(int i = 1; i <= n; i++) ans = max(ans, val[i]);
printf("%lld", ans);
return 0;
}