F. Dominant Indices
time limit per test4.5 seconds
memory limit per test512 megabytes
inputstandard input
outputstandard output
You are given a rooted undirected tree consisting of n vertices. Vertex 1 is the root.
Let’s denote a depth array of vertex x as an infinite sequence , where is the number of vertices y such that both conditions hold:
x is an ancestor of y;
the simple path from x to y traverses exactly i edges.
The dominant index of a depth array of vertex x (or, shortly, the dominant index of vertex x) is an index j such that:
for every
for every
.
For every vertex in the tree calculate its dominant index.
Input
The first line contains one integer
— the number of vertices in a tree.
Then lines follow, each containing two integers and . This line denotes an edge of the tree.
It is guaranteed that these edges form a tree.
Output
Output n numbers. i-th number should be equal to the dominant index of vertex i.
Examples
input
4
1 2
2 3
3 4
output
0
0
0
0
input
4
1 2
1 3
1 4
output
1
0
0
0
input
4
1 2
2 3
2 4
output
2
1
0
0
思路:树上启发式合并。记录每个节点的重儿子,对于一个节点,优先遍历轻儿子,最后遍历重儿子,保留重儿子信息,然后暴力查询轻儿子信息,合并到重儿子的信息上,然后更新答案。
最后,如果当前节点是重儿子,那就不清除当前信息;否则清除信息。
#include<bits/stdc++.h>
using namespace std;
const int MAX=1e6+10;
typedef long long ll;
int siz[MAX],L[MAX],R[MAX],son[MAX],all=0;
int d[MAX];
vector<int>e[MAX];
void dfs(int k,int fa,int dep)//记录每个节点重儿子以及深度
{
siz[k]=1;
L[k]=++all;
d[all]=dep;
for(int i=0;i<e[k].size();i++)
{
int nex=e[k][i];
if(nex==fa)continue;
dfs(nex,k,dep+1);
siz[k]+=siz[nex];
if(siz[son[k]]<siz[nex])son[k]=nex;
}
R[k]=all;
}
int ans[MAX];
int cnt[MAX]; //cnt[i]记录深度为i的节点个数
int lenka=0; //记录节点个数最多的深度
void cal(int k,int fa,int tp)
{
for(int i=0;i<e[k].size();i++)//优先遍历轻儿子
{
int nex=e[k][i];
if(nex==fa||nex==son[k])continue;
cal(nex,k,0);
}
if(son[k])cal(son[k],k,1); //最后遍历重儿子,此时重儿子的信息已被存入数组
cnt[d[L[k]]]++;
if(cnt[d[L[k]]]>cnt[lenka])lenka=d[L[k]];
if(cnt[d[L[k]]]==cnt[lenka]&&lenka>d[L[k]])lenka=d[L[k]];
for(int i=0;i<e[k].size();i++)//暴力将所有轻儿子的信息加入到cnt数组,并更新答案
{
int nex=e[k][i];
if(nex==fa||nex==son[k])continue;
for(int j=L[nex];j<=R[nex];j++)
{
cnt[d[j]]++;
if(cnt[d[j]]>cnt[lenka])lenka=d[j];
if(cnt[d[j]]==cnt[lenka]&&lenka>d[j])lenka=d[j];
}
}
ans[k]=lenka-d[L[k]];
if(tp==0) //当前节点不是重儿子,清楚信息
{
lenka=0;
for(int i=L[k];i<=R[k];i++)cnt[d[i]]--;
}
}
int main()
{
int n;
cin>>n;
for(int i=1;i<n;i++)
{
int x,y;
scanf("%d%d",&x,&y);
e[x].push_back(y);
e[y].push_back(x);
}
all=0;
dfs(1,0,0);
lenka=0;
cal(1,0,1);
for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
return 0;
}