传送门:CodeForces-1354E
思路分析
2只能和1或3连边,1和3不能连边
那么很显然是二分图,将每个连通块的点划分为两个集合,集合内的互相无边,集合间有连边
将其中一个集合染成2,剩下的部分1或者3随意,那么问题就是如果确定是否有方案能够满足2的数量为$n_2$
设$dp[i][j]$表示用了前$i$个连通块,能否组成数量为$j$,假设$dp[cnt][n_2]$成立,那么我们倒着来$dp$,如果最后$dp[0][0]=1$说明存在满足条件的方案,之后再从头开始标记答案就行了
样例输入
6 3
2 2 2
3 1
5 4
2 5
样例输出
YES
112323
AC代码
#include <bits/stdc++.h>
#define ls x<<1
#define rs x<<1|1
#define fi first
#define se second
#define ll long long
#define pb push_back
#define mp make_pair
#define fun function
#define sz(x) (x).size()
#define lowbit(x) (x)&(-x)
#define all(x) (x).begin(),(x).end()
#define mem(a,b) memset(a,b,sizeof(a))
namespace FastIO {
#define BUF_SIZE 100000
#define OUT_SIZE 100000
bool IOerror=0;
inline char nc() {
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if(p1==pend) {
p1=buf;
pend=buf+fread(buf,1,BUF_SIZE,stdin);
if(pend==p1) {
IOerror=1;
return -1;
}
}
return *p1++;
}
inline bool blank(char ch) {
return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';
}
template<class T> inline bool read(T &x) {
bool sign=0;
char ch=nc();
x=0;
for(; blank(ch); ch=nc());
if(IOerror)return false;
if(ch=='-')sign=1,ch=nc();
for(; ch>='0'&&ch<='9'; ch=nc())x=x*10+ch-'0';
if(sign)x=-x;
return true;
}
template<class T,class... U>bool read(T& h,U&... t) {
return read(h)&&read(t...);
}
#undef OUT_SIZE
#undef BUF_SIZE
};
using namespace std;
using namespace FastIO;
mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
const int INF = 0x3f3f3f3f;
const int N = 5e3+10;
int dp[N][N],ans[N],col[N];
int cnt,n,m,n1,n2,n3;
vector<int>e[N],s[N][2];
void dfs(int u,int x){
col[u]=x;
s[cnt][x==1].pb(u);
for(auto v:e[u]){
if(col[v]==0) dfs(v,-x);
else if(col[v]==col[u]){
cout<<"NO"<<endl;
exit(0);
}
}
}
int main() {
#ifdef xiaofan
freopen("1.in","r",stdin);
freopen("1.out","w",stdout);
#endif
read(n,m,n1,n2,n3);
for(int i=1;i<=m;i++){
int u,v;
read(u,v);
e[u].pb(v);
e[v].pb(u);
}
for(int i=1;i<=n;i++){
if(col[i]==0){
++cnt;
dfs(i,1);
}
}
dp[cnt][n2]=1;
for(int i=cnt;i>=1;i--){
int x=s[i][0].size();
int y=s[i][1].size();
for(int j=0;j<=n;j++){
if(j>=x) dp[i-1][j-x]|=dp[i][j];
if(j>=y) dp[i-1][j-y]|=dp[i][j];
}
}
if(dp[0][0]==0) return cout<<"NO",0;
cout<<"YES"<<endl;
int now=0;
for(int i=1;i<=cnt;i++){
int y=s[i][1].size();
int cur=dp[i][now+y];
for(auto v:s[i][cur]) ans[v]=2,now++;
for(auto v:s[i][cur^1]) {
if(n1) ans[v]=1,n1--;
else ans[v]=3;
}
}
for(int i=1;i<=n;i++) cout<<ans[i];
return 0;
}