Codeforces 1354E:Graph Coloring – 题解

主要思路

这个题还是比较简单的。

发现在生成树上放一个 \(2\) 之后,剩下与该点距离为偶数的点都已经确定了。所以对于一个连通块而言,被染成 \(2\) 的方式只有两种。

那么我们可以对这些连通块做一个背包,然后来判断是否有 \(n_2\) 的染色方案。

剩下的点随便染色即可。

代码

// CF1354E.cpp
#include <bits/stdc++.h>

using namespace std;

const int MAX_N = 5050, MAX_E = 2e5 + 200;

int n, m, ni[4], head[MAX_N], current, up[MAX_N], block_siz[MAX_N], block_root[MAX_N], tot;
int aff[MAX_N], cnt1[MAX_N], color[MAX_N], ans[MAX_N];
bool dp[MAX_N][MAX_N], stat[MAX_N];

struct edge
{
    int to, nxt;
} edges[MAX_E];

void addpath(int src, int dst)
{
    edges[current].to = dst, edges[current].nxt = head[src];
    head[src] = current++;
}

void dfs(int u, int fa, int col, int cur)
{
    aff[u] = col, cnt1[col] += cur, color[u] = cur, block_siz[col]++;
    for (int i = head[u]; i != -1; i = edges[i].nxt)
        if (aff[edges[i].to] == 0)
            dfs(edges[i].to, u, col, cur ^ 1);
}

int main()
{
    memset(head, -1, sizeof(head));
    scanf("%d%d%d%d%d", &n, &m, &ni[1], &ni[2], &ni[3]);
    for (int i = 1, u, v; i <= m; i++)
        scanf("%d%d", &u, &v), addpath(u, v), addpath(v, u);
    for (int i = 1; i <= n; i++)
        if (aff[i] == 0)
            dfs(i, 0, ++tot, 0), block_root[tot] = i;
    for (int u = 1; u <= n; u++)
        for (int i = head[u]; i != -1; i = edges[i].nxt)
            if (color[edges[i].to] == color[u])
                puts("NO"), exit(0);
    dp[0][0] = true;
    for (int i = 1; i <= tot; i++)
        for (int j = ni[2]; j >= 0; j--)
            dp[i][j] = (j >= cnt1[i] ? dp[i - 1][j - cnt1[i]] : false) || (j - (block_siz[i] - cnt1[i]) >= 0 ? dp[i - 1][j - (block_siz[i] - cnt1[i])] : false);
    if (!dp[tot][ni[2]])
        puts("NO"), exit(0);
    int tot_siz = ni[2];
    for (int i = tot; i >= 1; i--)
    {
        bool flag1 = (tot_siz >= cnt1[i] ? dp[i - 1][tot_siz - cnt1[i]] : false);
        // bool flag2 = (tot_siz - (block_siz[i] - cnt1[i]) >= 0 ? dp[tot_siz - (block_siz[i] - cnt1[i])] : false);
        if (flag1)
            stat[i] = true, tot_siz -= cnt1[i];
        else
            stat[i] = false, tot_siz -= (block_siz[i] - cnt1[i]);
    }
    puts("YES");
    for (int i = 1; i <= n; i++)
    {
        if ((color[i] == 1 && stat[aff[i]] == true) || (color[i] == 0 && stat[aff[i]] == false))
            ans[i] = 2;
        else if (ni[1] > 0)
            ans[i] = 1, ni[1]--;
        else
            ans[i] = 3, ni[3]--;
        printf("%d", ans[i]);
    }
    puts("");
    return 0;
}

Leave a Reply

Your email address will not be published. Required fields are marked *