BZOJ1086 王室联邦 —— 树分块
题目链接:https://vjudge.net/problem/HYSBZ-1086
1086: [SCOI2005]王室联邦
Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 2277 Solved: 1400
[Submit][Status][Discuss]
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
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
2 1 1 3 3 3 3 2
2 1 8
题意:
树分块,要求每一个分块的结点数范围为:[ B, 3B ]。
代码如下:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <vector> 6 #include <cmath> 7 #include <queue> 8 #include <stack> 9 #include <map> 10 #include <string> 11 #include <set> 12 using namespace std; 13 typedef long long LL; 14 const int INF = 2e9; 15 const LL LNF = 9e18; 16 const int MOD = 1e9+7; 17 const int MAXN = 1e3+10; 18 19 int N, B; 20 vector<int>g[MAXN]; 21 int id, belong[MAXN], cap[MAXN]; 22 int top, Stack[MAXN]; 23 24 void dfs(int u, int pre) 25 { 26 int now = top; 27 for(int i = 0; i<g[u].size(); i++) 28 { 29 int v = g[u][i]; 30 if(v==pre) continue; 31 dfs(v, u); 32 if(top-now>=B) // 个数范围为[B,2B) 33 { 34 cap[++id] = u; 35 while(top!=now) belong[Stack[--top]] = id; 36 } 37 } 38 Stack[top++] = u; 39 } 40 41 int main() 42 { 43 while(scanf("%d%d", &N,&B)!=EOF) 44 { 45 for(int i = 1; i<=N; i++) 46 g[i].clear(); 47 for(int i = 1; i<N; i++) 48 { 49 int u, v; 50 scanf("%d%d", &u,&v); 51 g[u].push_back(v); 52 g[v].push_back(u); 53 } 54 55 id = top = 0; 56 dfs(1, -1); 57 while(top>0) belong[Stack[--top]] = id; //把剩下的并入最后一个分块,个数范围为[B,3B) 58 59 printf("%d\n", id); 60 for(int i = 1; i<=N; i++) printf("%d ", belong[i]); putchar('\n'); 61 for(int i = 1; i<=id; i++) printf("%d ", cap[i]); putchar('\n'); 62 } 63 }