http://www.lydsy.com/JudgeOnline/problem.php?id=1086
思路:贪心,每次当储存的儿子大于等于B时,分出一个块,这样每次每个块至多为2B,这样剩下的没有被分的块小于B,可以加入任意一个块,都是合法的。
1 #include<algorithm> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<iostream> 6 int tot,go[200005],first[200005],next[200005],n,m; 7 int top,c[200005],pd,size[200005],cap[200005],belong[200005],sz; 8 int read(){ 9 char ch=getchar();int t=0,f=1; 10 while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();} 11 while ('0'<=ch&&ch<='9'){t=t*10+ch-'0';ch=getchar();} 12 return t*f; 13 } 14 void insert(int x,int y){ 15 tot++; 16 go[tot]=y; 17 next[tot]=first[x]; 18 first[x]=tot; 19 } 20 void add(int x,int y){ 21 insert(x,y);insert(y,x); 22 } 23 void dfs(int x,int fa){ 24 c[++top]=x; 25 for (int i=first[x];i;i=next[i]){ 26 int pur=go[i]; 27 if (pur==fa) continue; 28 dfs(pur,x); 29 if (size[x]+size[pur]>=m){ 30 cap[++sz]=x;size[x]=0; 31 while (c[top]!=x) belong[c[top--]]=sz; 32 }else size[x]+=size[pur]; 33 } 34 size[x]++; 35 } 36 void find(int x,int fa){ 37 if (belong[x]) { 38 pd=belong[x]; 39 return; 40 } 41 for (int i=first[x];i;i=next[i]){ 42 int pur=go[i]; 43 if (pur==fa) continue; 44 if (!pd) find(pur,x); 45 } 46 } 47 int main(){ 48 n=read();m=read(); 49 if (n<m){ 50 printf("0 "); 51 return 0; 52 } 53 if (m==1){ 54 printf("%d ",n); 55 for (int i=1;i<=n;i++) 56 printf("%d ",i); 57 printf(" "); 58 for (int i=1;i<=n;i++) 59 printf("%d ",i); 60 printf(" "); 61 return 0; 62 } 63 for (int i=1;i<n;i++){ 64 int x=read(),y=read(); 65 add(x,y); 66 } 67 dfs(1,0); 68 pd=0; 69 int cnt=0,th; 70 for (int i=1;i<=n;i++) 71 if (!belong[i]) cnt++,th=1; 72 if (cnt>=m){ 73 sz++; 74 cap[sz]=th; 75 for (int i=1;i<=n;i++) 76 if (!belong[i]) belong[i]=sz; 77 } 78 for (int i=1;i<=n;i++) 79 if (!belong[i]){ 80 if (!pd) find(i,0); 81 if (pd) belong[i]=pd; 82 } 83 printf("%d ",sz); 84 for (int i=1;i<=n;i++) 85 printf("%d ",belong[i]); 86 printf(" "); 87 for (int i=1;i<=sz;i++) 88 printf("%d ",cap[i]); 89 printf(" "); 90 }