http://codeforces.com/contest/1009/problem/F
讲解:http://codeforces.com/blog/entry/44351
讲解中的问题是解决树上结点特性查询,而本题是查询相对于一个结点每一层根的个数。
#include<bits/stdc++.h>
#define maxn 1000010
using namespace std;
typedef pair<int,int> P;
vector<int> G[maxn];
int sz[maxn];
int dep[maxn],cnt[maxn],ans[maxn];
priority_queue<P> q;
void getsz(int v,int fa)
{
sz[v]=1;
for(int i=0;i<G[v].size();i++)
{
if(G[v][i]!=fa)
{
dep[G[v][i]]=dep[v]+1;//记录每一个结点所在层数
getsz(G[v][i],v);
sz[v]+=sz[G[v][i]];
}
}
}
void add(int v,int fa)//加结点
{
cnt[dep[v]]++;
q.push(P(cnt[dep[v]],-dep[v]));//優先隊列維護每一層點的個數,點數相同的層數小的優先。
for(int i=0;i<G[v].size();i++)
{
if(G[v][i]!=fa)
add(G[v][i],v);
}
}
void del(int v,int fa)//删结点
{
cnt[dep[v]]--;
for(int i=0;i<G[v].size();i++)
{
if(G[v][i]!=fa)
del(G[v][i],v);
}
}
void dfs(int v,int fa,int keep)
{
int mx=-1,bigChild=-1;
for(int i=0;i<G[v].size();i++)//找到最大孩子
{
if(G[v][i]!=fa && sz[G[v][i]]>mx)
{
mx=sz[G[v][i]];
bigChild=G[v][i];
}
}
for(int i=0;i<G[v].size();i++)//先处理非最大孩子
{
if(G[v][i]!=fa && G[v][i]!=bigChild)
dfs(G[v][i],v,0);
}
if(bigChild!=-1)//处理最大孩子
dfs(bigChild,v,1);//只有两种情况不用删点,头结点或是最大孩子
for(int i=0;i<G[v].size();i++)
{
if(G[v][i]!=fa && G[v][i]!=bigChild)
add(G[v][i],v);
}
cnt[dep[v]]++;
q.push(P(cnt[dep[v]],-dep[v]));
ans[v]=-q.top().second-dep[v];//結點數最多的層的編號減去當前編號即是答案。
if(keep==0)
{
del(v,fa);
while(!q.empty())
q.pop();
}
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
for(int i=1;i<=n;i++)
G[i].clear();
while(!q.empty())
q.pop();
memset(cnt,0,sizeof(cnt));
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
getsz(1,-1);
dfs(1,-1,1);/**********/
for(int i=1;i<=n;i++)
printf("%d\n",ans[i]);
}
return 0;
}