题意
给定一棵以 11 为根,nn 个节点的树。设 d(u,x)d(u,x) 为 uu 子树中到 uu 距离为 xx 的节点数。
对于每个点,求一个最小的 kk,使得 d(u,k)d(u,k) 最大。
题解
和那个数颜色的题是一样的,就是一道标准的 dsu on tree 的模板题。当练手了。
代码
#include <bits/stdc++.h>
#define xx first
#define yy second
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N=1e6+10;
const int M=1e6+10;
int n,siz[N],dep[N],son[N],ans[N],cnt[N],Son,maxd;
vector<int> g[N];
void predfs(int u,int fa){
siz[u]=1;dep[u]=dep[fa]+1;
for(int v:g[u]){
if(v==fa) continue;
predfs(v,u);
siz[u]+=siz[v];
if(siz[v]>siz[son[u]]) son[u]=v;
}
}
void add(int u,int fa,int val){
cnt[dep[u]]+=val;
if(cnt[dep[u]]>cnt[maxd]||cnt[dep[u]]==cnt[maxd]&&dep[u]<maxd) maxd=dep[u];
for(int v:g[u]) if(v!=fa&&v!=Son) add(v,u,val);
}
void dfs(int u,int fa,bool keep){
for(int v:g[u]){
if(v==fa||v==son[u]) continue;
dfs(v,u,false);
}
if(son[u]) dfs(son[u],u,true);
Son=son[u];
add(u,fa,1);
ans[u]=maxd;
if(!keep) Son=0,add(u,fa,-1),maxd=0;
}
int main(){
scanf("%d",&n);
for(int i=1,u,v;i<n;i++){
scanf("%d%d",&u,&v);
g[u].push_back(v);
g[v].push_back(u);
}
predfs(1,0);
dfs(1,0,true);
for(int i=1;i<=n;i++) printf("%d
",ans[i]-dep[i]);
return 0;
}