长链剖分
将一棵树根据重儿子分为若干条极长链,然后将重儿子的状态直接转移到他的父亲
CF1009F模板
// author: M@
#define m_
//#define _DEBUG_
#include<iostream>
//#include<cstdio>
//#include<string.h>
//#include<iomanip>
//#include<queue>
//#include<vector>
//#include<map>
//#include<algorithm>
//#include<cmath>
//#include<list>
//#include<set>
//#include<string>
#define clr(a) memset((a),0,sizeof (a))
#define li idx<<1
#define ri idx<<1|1
using namespace std;
typedef unsigned int ui;
typedef long long LL;
typedef pair<int,int> pii;
const int INF=0x3f3f3f3f;
const LL LINF=1e18;
const double DINF=1e9;
const double EPS=1e-9;
const int maxn=1e6+5;
const int maxm = 3005;
int n;
struct edg{
int to, nxt;
}e[maxn * 2];
int son[maxn];
int *dp[maxn];
int ans[maxn];
int dep[maxn], ms[maxn];//³¤Á´ÆÊ·Ö
int cnt;
void add_edg(int x, int fx){
e[++cnt].to = x;
e[cnt].nxt = son[fx];
son[fx] = cnt;
}
int dfs0(int idx, int fa){
int mdep = 0;
ms[idx] = idx;
for(int i = son[idx]; i != 0; i = e[i].nxt){
int to = e[i].to;
if(to == fa){
continue;
}
int dd = dfs0(to, idx);
if(mdep < dd){
ms[idx] = to;
mdep = dd;
}
}
return mdep + 1;
}
int dfs(int idx, int fa, int td){
// printf("%d\n", idx);
// ans[idx] = 0;
if(ms[idx] == idx){
dp[idx] = new int [td + 1];
dp[idx][td] = 1;
ans[idx] = 0;
return 1;
}
int to = ms[idx];
int dd = dfs(to, idx, td + 1);
int ld = dd + 1;
dp[idx] = dp[to];
dp[idx][td] = 1;
ans[idx] = ans[to] + 1;
int mdd = 0;
for(int i = son[idx]; i != 0; i = e[i].nxt){
int to = e[i].to;
if(fa == to || ms[idx] == to){
continue;
}
int dd = dfs(to, idx, 0);
mdd = max(mdd, dd);
for(int j = 1; j <= dd; j++){
dp[idx][td + j] += dp[to][j - 1];
}
delete dp[to];
}
for(int i = 0; i <= mdd; i++){
if(dp[idx][td + i] > dp[idx][ans[idx] + td] || dp[idx][td + i] == dp[idx][ans[idx] + td] && i < ans[idx]){
ans[idx] = i;
}
// printf("dp[%d][%d] = %d ", idx, td+i, dp[idx][td+i]);
}
return ld;
// printf("idx: %d ", idx);
// for(int i = 0; i <= m; i++){
// printf("%d " , dp[idx][i]);
// }puts("");
}
int main()
{
#ifdef m_
freopen("input.txt","r",stdin);
// freopen("output.txt","w",stdout);
#endif
scanf("%d", &n);
cnt = 0;
for(int i = 1; i < n; i++){
int x, fx;
scanf("%d%d", &x, &fx);
add_edg(x ,fx);
add_edg(fx, x);
}
dfs0(1, 1);
dfs(1, 1, 0);
// for(int i = 1; i <= n; i++){
// printf("%d ", sNum[i]);
// }puts("");
// printf("%d\n", dp[midx]);
for(int i = 1; i <= n; i++){
printf("%d\n", ans[i]);
// printf("ms: %d\n", ms[i]);
}
#ifdef m_
fclose(stdin);
// fclose(stdout);
#endif
return 0;
}