大家都很强, 可与之共勉 。
我们开一个栈,遍历一个节点,若该节点的几棵子树的大小>=B,那么就把他们分到一块,省会为当前节点
这样做会剩下不到B个节点,这时候就利用栈传到上一层节点就可以
最后会剩下不到B个节点,因为我们原来的块都是一定不超过2B的,于是把这B个节点放到最后一个块也不会超过3B。
这里用到了贪心的思想。
1086: [SCOI2005]王室联邦
Description
“余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成
员来管理。他的国家有n个城市,编号为1..n。一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条
直接或间接的道路。为了防止管理太过分散,每个省至少要有B个城市,为了能有效的管理,每个省最多只有3B个
城市。每个省必须有一个省会,这个省会可以位于省内,也可以在该省外。但是该省的任意一个城市到达省会所经
过的道路上的城市(除了最后一个城市,即该省省会)都必须属于该省。一个城市可以作为多个省的省会。聪明的
你快帮帮这个国王吧!
Input
第一行包含两个数N,B(1<=N<=1000, 1 <= B <= N)。接下来N-1行,每行描述一条边,包含两个数,即这
条边连接的两个城市的编号。
Output
如果无法满足国王的要求,输出0。否则输出数K,表示你给出的划分方案中省的个数,编号为1..K。第二行输
出N个数,第I个数表示编号为I的城市属于的省的编号,第三行输出K个数,表示这K个省的省会的城市编号,如果
有多种方案,你可以输出任意一种。
Sample Input
8 2
1 2
2 3
1 8
8 7
8 6
4 6
6 5
Sample Output
3
2 1 1 3 3 3 3 2
2 1 8
HINT
Source
/**************************************************************
Problem: 1086
User: Lazer2001
Language: C++
Result: Accepted
Time:0 ms
Memory:916 kb
****************************************************************/
# define By_Lazer int main ( ) { return 0 ; }
// # define Local
# include <cctype>
# include <cstdio>
const size_t str = 1 << 16;
char buf[str], *ss, *tt ;
inline char pick ( ) {
return ( ss == tt ) ? ( tt = buf + fread ( ss = buf, 1, str , stdin ), *ss ++ ) : ( *ss ++ ) ;
}
inline int read ( ) {
static char ch;
static int x ;
while ( !isdigit ( ch = pick ( ) ) );
for ( x = -48 + ch ; isdigit ( ch = pick ( ) ) ; ( x *= 10 ) += ch - 48 );
return x ;
}
const int N = 1005 ;
struct edge {
int to, nxt ;
edge ( ) { }
edge ( int to, int nxt ) : to ( to ), nxt ( nxt ) { }
} g [ N << 1 ];
int ne = 1, head[N] ;
inline void AddDe ( int u, int v ) { g [ ++ ne ] = edge ( v, head[u] ) ; head[u] = ne ; g [ ++ ne ] = edge ( u, head[v] ) ; head[v] = ne ; }
int n, b ;
int place [N], cpt [N], cnt, stack [N], top ;
inline void Dfs ( int u, int fa ) {
int cur = top ;
for ( int i = head [u] ; i ; i = g [i].nxt ) {
int v = g [i].to ;
if ( v ^ fa ) {
Dfs ( v, u ) ;
if ( top - cur >= b ) {
cpt [ ++ cnt ] = u ;
while ( cur ^ top ) {
place [ stack [ top -- ] ] = cnt ;
}
}
}
}
stack [ ++ top ] = u ;
}
class Main {
public :
Main ( ) {
# ifdef Local
freopen ( "in.txt", "r", stdin ) ;
freopen ( "out.txt", "w", stdout ) ;
# endif
n = read ( ), b = read ( ) ;
for ( int i = 1 ; i < n ; ++ i ) AddDe ( read ( ), read ( ) ) ;
Dfs ( 1, 0 ) ;
while ( top ) place [ stack [top --] ] = cnt ;
printf ( "%d\n", cnt ) ;
for ( int i = 1 ; i <= n ; ++ i ) printf ( "%d%c", place [i], ( n ^ i ) ? ' ' : '\n' ) ;
for ( int i = 1 ; i <= cnt ; ++ i ) printf ( "%d%c", cpt [i], ( cnt ^ i ) ? ' ' : '\n' ) ;
}
} Z ;
By_Lazer