BZOJ1086 [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
 
 
正解:树上分块
解题报告:
  这道题只需要随意输出一组方案就可以了,似乎可以乱搞。。。
  考虑树上分块,每当扫到发现子树结点已经不小于B了,那么考虑把他们直接划成一个省,并且以当前根结点为省会即可。
  并且把子树中所有结点划到一个块中,用栈维护一下就可以了。那么最后会剩下一些结点,随便丢哪个块都是可以的,只要发现路上有一个点已经被划成某个块中,那么把接下来的子树中的点也都划成这个块即可,这样才能保证题目要求。
 
 1 //It is made by jump~
 2 #include <iostream>
 3 #include <cstdlib>
 4 #include <cstring>
 5 #include <cstdio>
 6 #include <cmath>
 7 #include <algorithm>
 8 #include <ctime>
 9 #include <vector>
10 #include <queue>
11 #include <map>
12 #include <set>
13 #ifdef WIN32   
14 #define OT "%I64d"
15 #else
16 #define OT "%lld"
17 #endif
18 using namespace std;
19 typedef long long LL;
20 const int MAXN = 1011;
21 int first[MAXN],to[MAXN*2],next[MAXN*2],size[MAXN];
22 int n,k,ecnt,B,cnt;
23 int que[MAXN],top;
24 int cap[MAXN];
25 int belong[MAXN];
26 
27 inline int getint()
28 {
29        int w=0,q=0;
30        char c=getchar();
31        while((c<'0' || c>'9') && c!='-') c=getchar();
32        if (c=='-')  q=1, c=getchar();
33        while (c>='0' && c<='9') w=w*10+c-'0', c=getchar();
34        return q ? -w : w;
35 }
36 
37 inline void dfs(int x,int fa){
38     que[++top]=x;
39     for(int i=first[x];i;i=next[i]) {
40     int v=to[i];
41     if(v==fa) continue;
42     dfs(v,x);
43     if(size[x]+size[v]>=B) {//子树超过范围
44         cap[++k]=x;//直接以子树为省,根为省会
45         while(que[top]!=x) belong[que[top--]]=k;
46         size[x]=0;
47     }else size[x]+=size[v];
48     }
49     size[x]++;
50 }
51 
52 inline void paint(int x,int fa,int col){//剩下的随便放
53     if(!belong[x])  belong[x]=col;
54     else col=belong[x];//练到当前块下
55     for(int i=first[x];i;i=next[i]) {
56     if(to[i]!=fa) paint(to[i],x,col);
57     }
58 }
59 
60 inline void work(){
61     n=getint(); B=getint(); int x,y;
62     for(int i=1;i<n;i++) {
63     x=getint(); y=getint();
64     next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y;
65     next[++ecnt]=first[y]; first[y]=ecnt; to[ecnt]=x;
66     }
67     dfs(1,0);
68     if(!k) cap[++k]=1;
69     paint(x,0,k);
70     printf("%d\n",k);
71     for(int i=1;i<=n;i++) printf("%d ",belong[i]);printf("\n");
72     for(int i=1;i<=k;i++) printf("%d ",cap[i]);
73 }
74 
75 int main()
76 {
77   work();
78   return 0;
79 }

 

posted @ 2016-07-27 22:12  ljh_2000  阅读(...)  评论(... 编辑 收藏