Loading [MathJax]/extensions/tex2jax.js

Codeforces 1354E:Graph Coloring – 题解

主要思路

这个题还是比较简单的。

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

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

剩下的点随便染色即可。

代码

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
// 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;
}
// 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; }
// 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 *