codeforces1354E. Graph Coloring

題意: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);
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章