ABC291Ex 题解
sunkuangzheng · · 题解
我们先忽略第一条限制,只考虑第二条限制。
很自然想到树的重心,我们知道一棵树重心为根时,最大的子树的
我们可以通过上面的方式,把重心之间连边,得到一棵新树。如果你这么写并直接提交,会发现已经 AC 了。现在我们来证明它满足第一条限制。
证明其实比较简单:
#include <bits/stdc++.h>
using namespace std;
const int N = 5e5+5;
int n,vis[N],u,v,siz[N],mx[N],rt,fa[N]; vector<int> g[N];
void dfs1(int u,int f){
siz[u] = 1,mx[u] = 0;
for(int v : g[u]) if(!vis[v] && v != f) dfs1(v,u),siz[u] += siz[v],mx[u] = max(mx[u],siz[v]);
}void getrt(int u,int f,int tot){
mx[u] = max(mx[u],tot - siz[u]);
if(mx[u] < mx[rt]) rt = u;
for(int v : g[u]) if(!vis[v] && v != f) getrt(v,u,tot);
}void dfs2(int u){
vis[u] = 1;
for(int v : g[u]) if(!vis[v]) rt = 0,dfs1(v,0),getrt(v,0,siz[v]),fa[rt] = u,dfs2(rt);
}int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin >> n; mx[0] = 1e9;
for(int i = 1;i < n;i ++) cin >> u >> v,g[u].push_back(v),g[v].push_back(u);
dfs1(1,0),getrt(1,0,n),fa[rt] = -1,dfs2(rt);
for(int i = 1;i <= n;i ++) cout << fa[i] << " ";
}
PS:我 AC 以后看别的题解,才知道我口胡的这东西就是点分树(