【块状树】BZOJ 1086: [SCOI2005]王室联邦
1086: [SCOI2005]王室联邦
Time Limit: 10 Sec Memory Limit: 162 MBSec Special JudgeSubmit: 826 Solved: 471
[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
很容易想到每次搜子树
不过好像每次搜索出的残余又要和回溯上去的子树凑
会非常麻烦
然后只能看题解
copy一下
因此我们在每次进入递归时维护一个栈底,对于当前子树来说这个栈底就是整个栈的底,栈底以下的元素不能修改或弹栈
这样当一棵子树深搜过后由于子树内未分块节点不超过b,之前搜过的未分块节点数也不超过b,因此每块不超过2b
那么题目为什么给了3b呢?
深搜结束后可能会剩余一些节点,这些节点的数量不超过b,而且一定与当前分出的最后一块连通
因此我们将剩余节点分到最后一块中,可以保证最后一块的大小不超过3b
因此我们在每次进入递归时维护一个栈底,对于当前子树来说这个栈底就是整个栈的底,栈底以下的元素不能修改或弹栈
这样当一棵子树深搜过后由于子树内未分块节点不超过b,之前搜过的未分块节点数也不超过b,因此每块不超过2b
那么题目为什么给了3b呢?
深搜结束后可能会剩余一些节点,这些节点的数量不超过b,而且一定与当前分出的最后一块连通
因此我们将剩余节点分到最后一块中,可以保证最后一块的大小不超过3b
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<algorithm> 5 6 #define maxn 1001 7 8 using namespace std; 9 10 inline int in() 11 { 12 int x=0;char ch=getchar(); 13 while(ch<'0'||ch>'9')ch=getchar(); 14 while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar(); 15 return x; 16 } 17 18 int n,l,last[maxn],tot=0,sta[maxn],top=0,father[maxn],root[maxn],cnt=0; 19 20 struct ed{ 21 int to,last; 22 }edge[maxn*2]; 23 24 void add(int u,int v) 25 { 26 edge[++tot].to=v,edge[tot].last=last[u],last[u]=tot; 27 edge[++tot].to=u,edge[tot].last=last[v],last[v]=tot; 28 } 29 30 void dfs(int poi,int Last) 31 { 32 int lim=top; 33 for(int i=last[poi];i;i=edge[i].last)if(edge[i].to!=Last){ 34 dfs(edge[i].to,poi); 35 if(top-lim>=l) 36 { 37 root[++cnt]=poi; 38 while(top!=lim)father[sta[top--]]=cnt; 39 } 40 } 41 sta[++top]=poi; 42 } 43 44 int main() 45 { 46 int u,v; 47 n=in();l=in(); 48 for(int i=1;i<n;i++) 49 u=in(),v=in(),add(u,v); 50 dfs(1,0); 51 while(top)father[sta[top--]]=cnt; 52 printf("%d\n",cnt); 53 for(int i=1;i<=n;i++)printf("%d ",father[i]); 54 printf("\n"); 55 for(int i=1;i<=cnt;i++)printf("%d ",root[i]); 56 return 0; 57 }