bzoj 1086: [SCOI2005]王室联邦

Description

  “余”人国的国王想重新编制他的国家。他想把他的国家划分成若干个省,每个省都由他们王室联邦的一个成员来管理。他的国家有n个城市,编号为1..n。一些城市之间有道路相连,任意两个不同的城市之间有且仅有一条直接或间接的道路。为了防止管理太过分散,每个省至少要有B个城市,为了能有效的管理,每个省最多只有3B个城市。每个省必须有一个省会,这个省会可以位于省内,也可以在该省外。但是该省的任意一个城市到达省会所经过的道路上的城市(除了最后一个城市,即该省省会)都必须属于该省。一个城市可以作为多个省的省会。聪明的你快帮帮这个国王吧!

解题报告

这题是另一种分块方法,从下往上做,回溯时入栈,当子树内的栈元素达到了B,我们就新建一个块,子数内的栈中元素加入块中,因为每一个子树块\(<B\),所以弹栈时 \(<2*B\),对于最后一个多出来的块也一定 \(<B\),如果 \(>=B\) 直接新建一个块,否则和上个块合并,由于块内元素 \(<2*B\),所以加入后 \(<3*B\)

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>
#define RG register
#define il inline
#define iter iterator
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
const int N=1005;
int n,B,head[N],num=0,nxt[N<<1],to[N<<1],cnt=0,st[N],top=0,fa[N],bel[N];
void link(int x,int y){nxt[++num]=head[x];to[num]=y;head[x]=num;}
void dfs(int x,int last){
   int u,s=top;
   for(int i=head[x];i;i=nxt[i]){
      u=to[i];if(u==last)continue;
      dfs(u,x);
      if(top-s>=B){
         fa[++cnt]=x;
         while(top!=s)bel[st[top--]]=cnt;
      }
   }
   st[++top]=x;
}
void work()
{
   int x,y;
   scanf("%d%d",&n,&B);
   for(int i=1;i<n;i++){
      scanf("%d%d",&x,&y);
      link(x,y);link(y,x);
   }
   dfs(1,1);
   while(top)bel[st[top--]]=cnt;
   printf("%d\n",cnt);
   for(int i=1;i<=n;i++)printf("%d ",bel[i]);
   puts("");
   for(int i=1;i<=cnt;i++)printf("%d ",fa[i]);
}

int main(){work();return 0;}
posted @ 2017-10-12 09:21  PIPIBoss  阅读(...)  评论(... 编辑 收藏