AC通道:http://www.lydsy.com/JudgeOnline/problem.php?id=1086
【题解】
树分块的裸题。
树分块的过程其实就是从根往下dfs,如果当前回溯的结点数超过了限制,就分出一个块,这个过程可以用一个栈来维护。
当dfs结束时,栈中还剩下一些点,这些点的数量不会超过b,把这些点放在最后一个块中即可。
/*************
bzoj 1086
by chty
2016.11.23
*************/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include<algorithm>
using namespace std;
#define FILE "read"
#define MAXN 1010
#define up(i,j,n) for(int i=j;i<=n;i++)
#define down(i,j,n) for(int i=j;i>=n;i--)
#define Auto(i,x) for(int i=Link[x];i;i=e[i].next)
#define cmax(a,b) a=max(a,b)
#define cmin(a,b) a=min(a,b)
namespace INIT{
char buf[1<<15],*fs,*ft;
inline char getc() {return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
inline int read(){
int x=0,f=1; char ch=getc();
while(!isdigit(ch)) {if(ch=='-') f=-1; ch=getc();}
while(isdigit(ch)) {x=x*10+ch-'0'; ch=getc();}
return x*f;
}
}using namespace INIT;
struct node{int y,next;}e[MAXN*2];
int n,B,len,top,bcnt,Link[MAXN],vis[MAXN],stack[MAXN],belong[MAXN],root[MAXN];
void insert(int x,int y) {e[++len].next=Link[x];Link[x]=len;e[len].y=y;}
void init(){
n=read(); B=read();
up(i,1,n-1) {int x=read(),y=read(); insert(x,y); insert(y,x);}
}
void dfs(int x){
vis[x]=1; int cnt=top;
Auto(i,x) if(!vis[e[i].y]){
dfs(e[i].y);
if(top-cnt>=B){
bcnt++;
root[bcnt]=x;
while(top!=cnt) belong[stack[top--]]=bcnt;
}
}
stack[++top]=x;
}
void output(){
while(top) belong[stack[top--]]=bcnt;
printf("%d\n",bcnt);
up(i,1,n) printf("%d ",belong[i]); printf("\n");
up(i,1,bcnt) printf("%d ",root[i]); printf("\n");
}
int main(){
freopen(FILE".in","r",stdin);
freopen(FILE".out","w",stdout);
init();
dfs(1);
output();
return 0;
}