BZOJ1086 [SCOI2005]王室联邦(树分块)
把树的结点分块,块内结点连通且个数[b,3b]。
一遍DFS,维护一个栈,设置一个虚拟栈底以保证连通,递归返回时判断栈内元素个数是否大于等于b,是则划分为一个块,最后剩下的与最后一个块划分在一起。
http://blog.csdn.net/popoqqq/article/details/42772237
1 #include<cstdio> 2 #include<cstring> 3 using namespace std; 4 #define MAXN 1111 5 struct Edge{ 6 int v,next; 7 }edge[MAXN<<1]; 8 int NE,head[MAXN]; 9 void addEdge(int u,int v){ 10 edge[NE].v=v; edge[NE].next=head[u]; 11 head[u]=NE++; 12 } 13 int b; 14 int root[MAXN],belong[MAXN],bn; 15 int stack[MAXN],top; 16 void dfs(int u,int fa){ 17 int buttom=top; 18 for(int i=head[u]; i!=-1; i=edge[i].next){ 19 int v=edge[i].v; 20 if(v==fa) continue; 21 dfs(v,u); 22 if(top-buttom>=b){ 23 root[++bn]=u; 24 while(top!=buttom){ 25 belong[stack[top--]]=bn; 26 } 27 } 28 } 29 stack[++top]=u; 30 } 31 int main(){ 32 int n,u,v; 33 scanf("%d%d",&n,&b); 34 NE=0; 35 memset(head,-1,sizeof(head)); 36 for(int i=1; i<n; ++i){ 37 scanf("%d%d",&u,&v); 38 addEdge(u,v); 39 addEdge(v,u); 40 } 41 dfs(1,1); 42 if(top && bn==0){ 43 putchar('0'); 44 return 0; 45 } 46 while(top){ 47 belong[stack[top--]]=bn; 48 } 49 printf("%d\n",bn); 50 for(int i=1; i<=n; ++i) printf("%d ",belong[i]); 51 putchar('\n'); 52 for(int i=1; i<=bn; ++i) printf("%d ",root[i]); 53 return 0; 54 }