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
解题思路: 看到这题就mengbier了,难道是树形DP,可是这个是输出方案怎么搞,而且3*b有什么用?啊,苦思无果,只能拜读各神牛题解了,听说是树分块的裸题???
其实我们DFS一遍就好了,对于当前一个点,如果子树大小超过B,直接把子树划分为一个省,当前根节点为省会就好了,如果子树大小小于B的话,就在当前根节点的父亲节点操作,为什么可以这么搞呢?可以参考这位同学的博客:见这里 但是我还有个疑问,按照这种做法,省会大小最大不超过2*B吧,为什么要限定3*B呢,虽然这样是不影响答案的,如果有知道的,一定要告诉小弟。。。
考虑操作。显然这需要一个栈来维护,每次回去之前将x加入栈里面。然后栈中在当前树中的节点超过b个时就将这b个放到一个省里。
代码如下:
//bzoj 1086
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2020;
int head[maxn], stk[maxn], cnt, top, idx, n, b;
int root[maxn], city[maxn];
struct edge{
int v, nxt;
edge(){}
edge(int v, int nxt) : v(v), nxt(nxt) {}
}E[maxn];
void init(){
cnt = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v){
E[cnt].v = v, E[cnt].nxt = head[u], head[u] = cnt++;
}
void dfs(int u, int fa){
int now = top;
for(int i = head[u]; ~i; i = E[i].nxt){
int v = E[i].v;
if(v == fa) continue;
dfs(v, u);
if(top - now >= b){
root[++idx] = u;
while(top != now){
city[stk[top--]] = idx;
}
}
}
stk[++top] = u;
}
int main(){
scanf("%d%d", &n, &b);
init();
for(int i = 1; i < n; i++){
int u, v;
scanf("%d%d", &u, &v);
addedge(u, v);
addedge(v, u);
}
dfs(1, -1);
while(top){
city[stk[top--]] = idx;
}
cout << idx << endl;
for(int i = 1; i <= n; i++) cout << city[i] << " "; cout << endl;
for(int i = 1; i <= idx; i++) cout << root[i] << " "; cout << endl;
return 0;
}