洛谷传送门
Codeforces传送门
题意翻译
给出一棵有根树,对于每个节点 x x x,定义一个无穷序列 d d d,其中 d ( x , i ) d(x,i) d(x,i)表示以 x x x为根节点的子树中到 x x x的距离恰好为 i i i的点的个数, i = 0 ∼ ∞ i=0\sim \infin i=0∼∞,现在对每个点 x x x,希望求出一个值 j j j,使得对于任意 k < j k<j k<j, d ( x , k ) < d ( x , j ) d(x,k)<d(x,j) d(x,k)<d(x,j),对于任意 k > j , d ( x , k ) ≤ d ( x , j ) k>j,d(x,k)\le d(x,j) k>j,d(x,k)≤d(x,j)
输入输出格式
输入格式:
第一行一个整数 n n n,表示树的节点个数 接下来 n − 1 n-1 n−1行,每行两个整数, x x x, y y y,表示 x , y x,y x,y之间有一条连边
输出格式:
n n n行,每行一个整数,第 i i i行表示 x = i x=i x=i时对应的 j j j
输入输出样例
输入样例#1:
4
1 2
2 3
3 4
输出样例#1:
0
0
0
0
输入样例#2:
4
1 2
1 3
1 4
输出样例#2:
1
0
0
0
输入样例#3:
4
1 2
2 3
2 4
输出样例#3:
2
1
0
0
解题分析
长链剖分模板题。没什么好说的…
注意转移重儿子的时候写假了还能过138个点…
代码如下:
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 1005000
template <class T>
IN void in(T &x)
{
x = 0; R char c = gc;
for (; !isdigit(c); c = gc);
for (; isdigit(c); c = gc)
x = (x << 1) + (x << 3) + c - 48;
}
int n, cnt;
struct Edge {int to, nex;} edge[MX << 1];
int buf[MX << 2], *dp[MX], *pt = buf;
int dep[MX], head[MX], son[MX], ans[MX];
IN void add(R int from, R int to)
{edge[++cnt] = {to, head[from]}, head[from] = cnt;}
void DFS(R int now, R int fa)
{
for (R int i = head[now]; i; i = edge[i].nex)
{
if (edge[i].to == fa) continue;
DFS(edge[i].to, now);
if (dep[edge[i].to] > dep[son[now]]) son[now] = edge[i].to;
}
dep[now] = dep[son[now]] + 1;
}
IN void nw(R int now) {dp[now] = pt; pt += dep[now] + 2;}
void DP(R int now, R int fa)
{
int mx = 0;
dp[now][0] = 1;
if (!son[now]) return;
dp[son[now]] = dp[now] + 1;
DP(son[now], now); ans[now] = ans[son[now]] + 1; mx = dp[now][ans[now]];
for (R int i = head[now]; i; i = edge[i].nex)
{
if (edge[i].to == fa || edge[i].to == son[now]) continue;
nw(edge[i].to);
DP(edge[i].to, now);
for (R int j = 0; j < dep[edge[i].to]; ++j)
{
dp[now][j + 1] += dp[edge[i].to][j];
if (dp[now][j + 1] > mx) ans[now] = j + 1, mx = dp[now][j + 1];
else if (dp[now][j + 1] == mx && ans[now] > j + 1) ans[now] = j + 1;
}
}
if (dp[now][ans[now]] == 1) ans[now] = 0;
}
int main(void)
{
in(n); int foo, bar;
for (R int i = 1; i < n; ++i)
in(foo), in(bar), add(foo, bar), add(bar, foo);
DFS(1, 0); nw(1);
DP(1, 0);
for (R int i = 1; i <= n; ++i) printf("%d\n", ans[i]);
}