Bzoj1086 [SCOI2005]王室联邦
Submit: 1749 Solved: 1056
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
HINT
Source
树 贪心 (伪)树分块
听说是树分块裸题……喜+1系列
按DFS序遍历整棵树,发现子树大小大于B,就把它们划成一块
这样分出来,每棵子树的大小都在B~2B之间。
最后还会剩下一些零碎的结点,它们的总数小于B(不然就被划分了),把它们拼到最近的块里,该块尺寸不会超过3B,满足要求。
n<B时无解
写啥WA啥系列,34行把cnt写成u挂了一次
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<queue> 6 using namespace std; 7 const int mxn=2010; 8 int read(){ 9 int x=0,f=1;char ch=getchar(); 10 while(ch<'0' || ch>'9'){if(ch=='-')f=-1;ch=getchar();} 11 while(ch>='0' && ch<='9'){x=x*10-'0'+ch;ch=getchar();} 12 return x*f; 13 } 14 struct edge{ 15 int v,nxt; 16 }e[mxn<<1]; 17 int hd[mxn],mct=0; 18 void add_edge(int u,int v){ 19 e[++mct].v=v;e[mct].nxt=hd[u];hd[u]=mct;return; 20 } 21 // 22 int n,B; 23 int t[mxn],C[mxn],sz[mxn]; 24 int st[mxn],top=0,cnt=0; 25 void DFS(int u,int fa){ 26 st[++top]=u; 27 for(int i=hd[u],v;i;i=e[i].nxt){ 28 v=e[i].v; 29 if(v==fa)continue; 30 DFS(v,u); 31 if(sz[u]+sz[v]>=B){ 32 C[++cnt]=u; 33 while(st[top]!=u){ 34 t[st[top--]]=cnt; 35 } 36 sz[u]=0; 37 } 38 else sz[u]+=sz[v]; 39 } 40 ++sz[u]; 41 return; 42 } 43 void DFS2(int u,int fa,int c){ 44 if(!t[u])t[u]=c; 45 else c=t[u]; 46 for(int i=hd[u];i;i=e[i].nxt){ 47 if(e[i].v==fa)continue; 48 DFS2(e[i].v,u,c); 49 } 50 return; 51 } 52 int main(){ 53 int i,j,u,v; 54 n=read();B=read(); 55 if(n<B){printf("0\n");return 0;} 56 for(i=1;i<n;i++){ 57 u=read();v=read(); 58 add_edge(u,v);add_edge(v,u); 59 } 60 DFS(1,0); 61 // 62 if(!cnt){C[cnt=1]=1;} 63 DFS2(1,0,cnt); 64 printf("%d\n",cnt); 65 for(i=1;i<=n;i++){printf("%d ",t[i]);}printf("\n"); 66 for(i=1;i<=cnt;i++){printf("%d ",C[i]);}printf("\n"); 67 return 0; 68 }
本文为博主原创文章,转载请注明出处。