一开始做的时候脑残了,以为会出现很多无解的情况,于是加了一堆特判,果断WA。
后来发现,明明只有n<B的时候才无解啊。
然后发现题意理解错了。。。。
原来多颗子树可以由根连接成省,而根可以在省外。。。。。。。
于是我们有个贪心的方法。
当前节点的子树集的大小一旦大于等于B,直接分成一个省,当然我们还可以证明这个省的城市数<=2B。
最后还有一些<B的省,直接塞到别的省就好了。
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct Edge{int to,next;}e[2010];
int head[1005],cnt,k;
void ins(int u,int v){
cnt++;e[cnt].to=v;e[cnt].next=head[u];head[u]=cnt;
}
int B,sz[1005],q[1005],top,cap[1005],pro,belong[1005];
void dfs(int u,int fa){
q[++top]=u;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa)continue;
dfs(v,u);
if(sz[u]+sz[v]>=B){
sz[u]=0;
cap[++pro]=u;
while(q[top]!=u)
belong[q[top--]]=pro;
}else sz[u]+=sz[v];
}
sz[u]++;
}
void set(int u,int fa,int anc){
if(belong[u])anc=belong[u];
else belong[u]=anc;
for(int i=head[u];i;i=e[i].next){
int v=e[i].to;
if(v==fa)continue;
set(v,u,anc);
}
}
int main(){
int n;
scanf("%d%d",&n,&B);
if(n<B){printf("0");return 0;}
int u,v;
for(int i=1;i<n;i++){
scanf("%d%d",&u,&v);
ins(u,v);ins(v,u);
}
dfs(1,0);
if(!pro)cap[++pro]=1;
set(1,0,pro);
printf("%d\n",pro);
for(int i=1;i<=n;i++)printf("%d ",belong[i]);
printf("\n");
for(int i=1;i<=pro;i++)printf("%d ",cap[i]);
return 0;
}