題意:n個點m條邊的無向圖,要求給n個點賦值,每個點可以賦爲1、2、3中的一個,n個點共有n1個值爲1的點,n2個值爲2的點,n3個值爲3的點,要求每條邊兩端點的差剛好爲1
二分圖染色,1,3實質是相同的,將圖分爲多個二分連通塊,然後找一下能否剛好n2個點
#include<bits/stdc++.h>
using namespace std;
vector<int>g[5005],sum[5005][2];
int n, m;
int a, b, c,k;
int col[5005];
int ok = 1;
int cnt;
int dp[5005][5005];
char ans[5005];
void dfs(int u, int f, int color)
{
col[u] = color;
sum[cnt][color].push_back(u);
for (auto v : g[u])
{
if (v == f)continue;
if (col[v] == -1)
{
dfs(v, u, !color);
}
else if (col[v] == col[u])ok = 0;
}
}
int main()
{
cin >> n >> m;
cin >> a >> b >> c;
while (m--)
{
int x, y;
cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
memset(col, -1, sizeof(col));
for (int i = 1; i <= n; i++)
{
if (col[i] == -1)
{
dfs(i, 0, 1);
cnt++;
}
}
if (!ok)
{
printf("NO\n");
}
else
{
dp[0][0] = 1;
for (int i = 0; i < cnt; i++)
{
int x = sum[i][0].size(), y = sum[i][1].size();
for (int j = 0; j <= b; j++)
{
if (dp[i][j])
{
if (j + y <= b)dp[i + 1][j + y] = 1;
if (j + x <= b)dp[i + 1][j + x] = 1;
}
}
}
//cout << cnt <<" "<< b << endl;
if (!dp[cnt][b])
{
printf("NO\n");
}
else
{
k = b;
for (int i = cnt; i > 0; i--)
{
int v;
if (dp[i - 1][k - sum[i - 1][0].size()])v = 0;
else v = 1;
k -= sum[i - 1][v].size();
for (auto xx : sum[i - 1][v])
{
ans[xx] = '2';
}
}
for (int i = 1; i <= n; i++)
{
if (ans[i] != '2') {
if (a)ans[i] = '1', a--;
else ans[i] = '3';
}
}
printf("YES\n%s\n", ans + 1);
}
}
}