您的位置:首页 > 其它

BZOJ 1086 王室联邦

2016-06-14 09:06 232 查看
http://www.lydsy.com/JudgeOnline/problem.php?id=1086

思路:贪心,每次当储存的儿子大于等于B时,分出一个块,这样每次每个块至多为2B,这样剩下的没有被分的块小于B,可以加入任意一个块,都是合法的。

#include<algorithm>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<iostream>
int tot,go[200005],first[200005],next[200005],n,m;
int top,c[200005],pd,size[200005],cap[200005],belong[200005],sz;
int read(){
char ch=getchar();int t=0,f=1;
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();}
return t*f;
}
void insert(int x,int y){
tot++;
go[tot]=y;
next[tot]=first[x];
first[x]=tot;
}
void add(int x,int y){
insert(x,y);insert(y,x);
}
void dfs(int x,int fa){
c[++top]=x;
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
dfs(pur,x);
if (size[x]+size[pur]>=m){
cap[++sz]=x;size[x]=0;
while (c[top]!=x) belong[c[top--]]=sz;
}else size[x]+=size[pur];
}
size[x]++;
}
void find(int x,int fa){
if (belong[x]) {
pd=belong[x];
return;
}
for (int i=first[x];i;i=next[i]){
int pur=go[i];
if (pur==fa) continue;
if (!pd) find(pur,x);
}
}
int main(){
n=read();m=read();
if (n<m){
printf("0\n");
return 0;
}
if (m==1){
printf("%d\n",n);
for (int i=1;i<=n;i++)
printf("%d ",i);
printf("\n");
for (int i=1;i<=n;i++)
printf("%d ",i);
printf("\n");
return 0;
}
for (int i=1;i<n;i++){
int x=read(),y=read();
add(x,y);
}
dfs(1,0);
pd=0;
int cnt=0,th;
for (int i=1;i<=n;i++)
if (!belong[i]) cnt++,th=1;
if (cnt>=m){
sz++;
cap[sz]=th;
for (int i=1;i<=n;i++)
if (!belong[i]) belong[i]=sz;
}
for (int i=1;i<=n;i++)
if (!belong[i]){
if (!pd) find(i,0);
if (pd) belong[i]=pd;
}
printf("%d\n",sz);
for (int i=1;i<=n;i++)
printf("%d ",belong[i]);
printf("\n");
for (int i=1;i<=sz;i++)
printf("%d ",cap[i]);
printf("\n");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: