题目大意
给定一棵 n 个点的树,求每个点至少需要删除多少条边,然后重新加上同等数量的边才能成为树的重心。
Data Constraint
题解
首先,删掉边后重新连边必然是连在根上。
设
fi
表示保证
i
的子树大小小于等于
然后在
O(n)
的换根,求出以每个点为根的答案。
时间复杂度: O(n)
SRC
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std ;
#define N 1000000 + 10
struct Note {
int ct , sz ;
Note ( int X = 0 , int Y = 0 ) { ct = X , sz = Y ; }
} f[N] , fa[N] ;
int Node[2*N] , Next[2*N] , Head[N] , tot ;
int Qs[N] ;
int n ;
int ans[N] ;
int Read() {
int ret = 0 ;
char ch = getchar() ;
while ( ch < '0' || ch > '9' ) ch = getchar() ;
while ( ch >= '0' && ch <= '9' ) {
ret = ret * 10 + ch - '0' ;
ch = getchar() ;
}
return ret ;
}
void link( int u , int v ) {
Node[++tot] = v ;
Next[tot] = Head[u] ;
Head[u] = tot ;
}
void DFS( int x , int F ) {
f[x].ct = 0 ;
f[x].sz = 1 ;
int Cnt = 0 ;
for (int p = Head[x] ; p ; p = Next[p] ) {
if ( Node[p] == F ) continue ;
DFS( Node[p] , x ) ;
f[x].ct += f[Node[p]].ct ;
}
for (int p = Head[x] ; p ; p = Next[p] ) {
if ( Node[p] == F ) continue ;
Qs[++Cnt] = f[Node[p]].sz ;
}
ans[x] = f[x].ct ;
sort( Qs + 1 , Qs + Cnt + 1 ) ;
for (int i = 1 ; i <= Cnt ; i ++ ) {
if ( 2 * (f[x].sz + Qs[i]) <= n ) f[x].sz += Qs[i] ;
else f[x].ct ++ ;
}
}
void Move( int x , int F ) {
f[x].sz = 1 , f[x].ct = fa[x].ct ;
ans[x] += f[x].ct ;
int Cnt = 0 ;
Qs[++Cnt] = fa[x].sz ;
for (int p = Head[x] ; p ; p = Next[p] ) {
if ( Node[p] == F ) continue ;
f[x].ct += f[Node[p]].ct ;
Qs[++Cnt] = f[Node[p]].sz ;
}
sort( Qs + 1 , Qs + Cnt + 1 ) ;
int wz = 0 ;
for (int i = 1 ; i <= Cnt ; i ++ ) {
if ( 2 * (f[x].sz + Qs[i]) <= n ) f[x].sz += Qs[i] ;
else {
f[x].ct ++ ;
if ( !wz ) wz = i ;
}
}
for (int p = Head[x] ; p ; p = Next[p] ) {
if ( Node[p] == F ) continue ;
int Son = Node[p] ;
fa[Son].sz = f[x].sz - f[Son].sz ;
fa[Son].ct = f[x].ct - f[Son].ct ;
if ( wz ) {
if ( f[Son].sz < Qs[wz] ) {
if ( 2 * (fa[Son].sz + Qs[wz]) <= n ) fa[Son].sz += Qs[wz] , fa[Son].ct -- ;
} else fa[Son].sz += f[Son].sz , fa[Son].ct -- ;
}
}
for (int p = Head[x] ; p ; p = Next[p] ) {
if ( Node[p] == F ) continue ;
Move( Node[p] , x ) ;
}
}
int main() {
freopen( "flea.in" , "r" , stdin ) ;
freopen( "flea.out" , "w" , stdout ) ;
n = Read() ;
for (int i = 1 ; i < n ; i ++ ) {
int u = Read() , v = Read() ;
link( u , v ) ;
link( v , u ) ;
}
DFS( 1 , 0 ) ;
Move( 1 , 0 ) ;
for (int i = 1 ; i <= n ; i ++ ) printf( "%d\n" , ans[i] ) ;
return 0 ;
}
以上.