Educational Codeforces Round 87 (Rated for Div. 2) E. Graph Coloring 并查集

题目链接
题意:给你一个图,你要给每个点染色(1,2,3),满足相邻点奇偶不同,且颜色数量给定。
思路:
显然这张图的所有连通块必然都是二分图,否则存在奇环的话就必然不合法。
那么先用并查集处理出所有连通块的两侧大小,用记录路径的dp处理出染2的方案就做完了。
并查集判断二分图的一些细节见:此处

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N = 2e5 + 10;
#define fi first
#define se second
#define pb push_back
#define mp make_pair
int n,m,col[5];
vector<int>v[N];
int f[N],sz[N];
int find(int x){
	return f[x]==x?x:(f[x]=find(f[x]));
}
struct uzi{
	int i,l,r;
}p[N];
int cnt;
int vis[5003][5003],ch[5555];
int main() {
  ios::sync_with_stdio(false);
  cin>>n>>m;
  for(int i=1;i<=n;i++)f[i]=i,sz[i]=1;
  for(int i=n+1;i<=2*n;i++)f[i]=i;
  for(int i=1;i<=3;i++)cin>>col[i];
  for(int i=1;i<=m;i++){
  	int s,t;
  	cin>>s>>t;
  	v[s].pb(t);
  	v[t].pb(s);
  	int x=find(s),y=find(t+n);
  	if(x!=y)f[x]=y,sz[y]+=sz[x];
  	x=find(s+n),y=find(t);
  	if(x!=y)f[x]=y,sz[y]+=sz[x];
  }
  if(!col[2]){
  	if(m)cout<<"NO\n";
  	else{
  		cout<<"YES\n";
  		for(int i=1;i<=n;i++){
  			if(col[1])cout<<1,col[1]--;
  			else cout<<3;
  		}
  	}
  	return 0;
  }
  for(int i=1;i<=n;i++){
  	if(find(i)==find(i+n))return cout<<"NO\n",0;
  }
  int ze=0,l=0,r=0;
  for(int i=1;i<=n;i++){
  	if(find(i)==i){
  		if(sz[i]+sz[find(i+n)]==1){
  			p[++cnt]={i,sz[i],sz[find(i+n)]};
  		}else{
  			p[++cnt]={i,sz[find(i)],sz[find(i+n)]};
  		}
  	}
  }
  vis[cnt+1][0]=1;
  //找到一组解 记录路径 
  for(int i=cnt;i>=1;i--){
  	for(int j=0;j<=col[2];j++){
  		if(vis[i+1][j]){
  			if(j+p[i].l<=col[2])vis[i][j+p[i].l]=i;
  			if(j+p[i].r<=col[2])vis[i][j+p[i].r]=i;
  		}
  	}
  	for(int j=0;j<=col[2];j++){
  		if(!vis[i][j])vis[i][j]=vis[i-1][j];
  	}
  }
  if(vis[1][col[2]]){
  	int sum=col[2];
  	int now=1;
  	while(sum){
  		int x=sum-p[now].l,dx=vis[now][sum];
  		int y=sum-p[now].r,dy=vis[now][sum];
  		if(vis[dx+1][x]){
  			ch[p[now].i]=1;
  			sum-=p[now].l;
  			now=dx+1;
  		}else{
  			sum-=p[now].r;
  			now=dy+1;
  		}
  	}
  	cout<<"YES\n";
  	for(int i=1;i<=n;i++){
  		int x=find(i),st=0;
  		if(x>n)x-=n,st=1;
  		if(ch[x]){
  			if(!st)cout<<2;
  			else {
  				if(col[1])col[1]--,cout<<1;
  				else cout<<3;
  			}
  		}else{
  			if(!st){
   				if(col[1])col[1]--,cout<<1;
  				else cout<<3; 				
  			}else cout<<2;
  		}
  	}
  }else cout<<"NO\n";
 	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40655981/article/details/106236889