QOJ2605 题解

题意:给定 \(n,m,k\),给出一个 \(n\) 个点 \(m\) 条边的无向图,要求给每个点染成红、蓝、灰三种颜色之一,使得:

  • 和每个红点相连的蓝点个数不少于 \(k+1\)
  • 和每个蓝点相连的红点个数不少于 \(k+1\)

保证 \(m\ge 2nk\)


对于一个无向图 \(G\),我们总可以把点集划分成两部分 \(S,T\),使得两端不在同一个集合内的边的个数至少是 \(\frac{m}{2}\)。这个增量构造即可。

对应到本题中,也就是我们可以给每个点按照上述方式染成蓝色/红色,使得蓝红两个集合之间的边数至少为 \(nk\)

考虑先这样染色后再调整。如果当前仍然不合法,那么必定有一个点 \(x\) 满足 \(x\) 的度数(这里只考虑连向另一个集合的边)小于 \(k+1\)。直接删去这个点以及和他相连的边。

因为每次删去的边数不超过 \(k\),所以“边数不小于点数的 \(k\) 倍”这一条件总是成立。于是可以推出 \(kn\le m\le \frac{n^2}{4}\),这意味着剩下的点数 \(n\) 不会小于 \(4k\),因此调整一定会结束,这样我们就得到了一个合法的染色方案。

#include <bits/stdc++.h>

using namespace std;

const int N = 5e4 + 10;

int n, m, k, col[N], d[N];
vector<int> g[N];

void solve()
{
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++) g[i].clear(), col[i] = 0;
    for (int i = 1, u, v; i <= m; i++) cin >> u >> v, g[u].push_back(v), g[v].push_back(u);
    
    for (int i = 1; i <= n; i++)
    {
        int c[2]{};
        for (int x : g[i]) 
            if (x < i) c[col[x]]++;
        if (c[0] > c[1]) col[i] = 1;
        else col[i] = 0;
    }

    struct S
    {
        int d, i;

        bool operator< (const S& s2) const
        {
            return d == s2.d ? i < s2.i : d < s2.d;
        }
    };

    set<S> s;
    memset(d, 0, sizeof(int) * (n + 1));

    for (int i = 1; i <= n; i++)
    {
        for (int x : g[i])
            if (col[x] != col[i]) d[i]++;
        s.insert({d[i], i});
    }

    while (s.begin()->d <= k)
    {
        auto it = s.begin();
        int i = it->i;
        for (int x : g[i])
            if (col[x] == (col[i] ^ 1)) s.erase({d[x], x}), d[x]--, s.insert({d[x], x});
        s.erase(it), col[i] = -1;
    }

    vector<int> r, b;
    for (int i = 1; i <= n; i++)
    {
        if (col[i] == 0) b.push_back(i);
        if (col[i] == 1) r.push_back(i);
    }

    cout << r.size() << '\n';
    for (int x : r) cout << x << ' '; cout << '\n';
    cout << b.size() << '\n';
    for (int x : b) cout << x << ' '; cout << '\n';
}

signed main()
{
    int t; cin >> t;
    while (t--) solve();
}
posted @ 2025-02-04 20:36  user_10086  阅读(69)  评论(0)    收藏  举报