不妨设$ale ble c$,那么相当于要找到两个大小至少为$a$和$b$的连通块(连通块可以通过删除度最小的点变小)
以一个点为根建出dfs树并对以下情况分类讨论:
1.存在一个节点满足$max(max_{son}(sz[son]),n-sz[k]+s)<a$(其中$sz[k]$表示k子树大小,$s$表示删除$k$后仍然与根联通的点个数),那么必然无解(两个连通块必然都需要经过$k$)
2.不存在,那么必然有解,且可以通过以下方法构造:
(1)找到任意一个满足$sz[k]ge a$且$max_{son}(sz[son])<a$的点$k$
(2)若$n-sz[k]+sge b$,将在$k$子树中且删去$k$后无法与根联通的$x$加入$S_{a}$,对于剩下的子树不断加入$S_{a}$直到$S_{a}$大小不小于$a$,然后剩下的点归入$S_{b}$
由于$max_{son}(sz[son])<a$,因此$S_{a}$的大小最多为$2a$,那么$|S_{b}|=n-2age n-a-c=b$
(3)若$n-sz[k]+s<b$,由于$ble lfloor frac{n}{2}
floor$,因此$sz[k]>lceil frac{n}{2}
ceil+s>b$,同时$n-sz[k]+sge a$(否则无解),那么交换$a$和$b$后用同样的方法即可
(代码中有一些小问题,可以通过随机根解决QAQ)
View Code
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 100005 4 struct ji{ 5 int nex,to; 6 }edge[N<<2]; 7 pair<int,int>a[11]; 8 int E,r,n,m,x,y,flag,head[N],sz[N],dfn[N],low[N],tot[N],ans[N]; 9 void add(int x,int y){ 10 edge[E].nex=head[x]; 11 edge[E].to=y; 12 head[x]=E++; 13 } 14 void update(int k,int p){ 15 if ((!a[p].first)||(ans[k]))return; 16 a[p].first--; 17 ans[k]=a[p].second; 18 for(int i=head[k];i!=-1;i=edge[i].nex) 19 if (edge[i].to)update(edge[i].to,p); 20 } 21 void dfs(int k,int fa){ 22 int mx=0,s=0; 23 sz[k]=1; 24 dfn[k]=low[k]=++x; 25 for(int i=head[k];i!=-1;i=edge[i].nex) 26 if (!sz[edge[i].to]){ 27 dfs(edge[i].to,k); 28 if (flag)return; 29 sz[k]+=sz[edge[i].to]; 30 low[k]=min(low[k],low[edge[i].to]); 31 if (low[edge[i].to]<dfn[k])s+=sz[edge[i].to]; 32 } 33 else{ 34 if (edge[i].to!=fa)low[k]=min(low[k],dfn[edge[i].to]); 35 edge[i].to=0; 36 } 37 if ((mx<a[1].first)&&(sz[k]>=a[1].first)){ 38 flag=2; 39 if (n-sz[k]+s<a[1].first){ 40 flag=1; 41 return; 42 } 43 if (n-sz[k]+s<a[2].first)swap(a[1],a[2]); 44 ans[k]=a[1].second; 45 a[1].first--; 46 for(int i=head[k];i!=-1;i=edge[i].nex) 47 if ((edge[i].to)&&(low[edge[i].to]>=dfn[k]))update(edge[i].to,1); 48 for(int i=head[k];i!=-1;i=edge[i].nex) 49 if ((edge[i].to)&&(low[edge[i].to]<dfn[k]))update(edge[i].to,1); 50 update(r,2); 51 for(int i=1;i<=n;i++) 52 if (!ans[i])ans[i]=a[3].second; 53 } 54 } 55 int main(){ 56 srand(time(0)); 57 scanf("%d%d",&n,&m); 58 r=rand()%n+1; 59 for(int i=1;i<=3;i++){ 60 scanf("%d",&a[i].first); 61 a[i].second=i; 62 } 63 sort(a+1,a+4); 64 memset(head,-1,sizeof(head)); 65 for(int i=1;i<=m;i++){ 66 scanf("%d%d",&x,&y); 67 add(x+1,y+1); 68 add(y+1,x+1); 69 } 70 dfs(r,0); 71 for(int i=1;i<=n;i++)printf("%d ",ans[i]); 72 }