[CF1470D] Strange Housing

[CF1470D] Strange Housing - 树

Description

给定一个 (n) 个节点,(m) 条无向边的图,现在你要给一些点染色,使得一条边所连接的两个点不能都被染色,在所有连接两个不被染色的点的边都被删除的情况下,这个图满足任意两个点互相可达。如果有染色方案输出所有被染色的点的编号。

Solution

任意找一棵生成树,DFS 它,对于一个点,如果周围没有已经选择的点就选择当前点

可以用反证法证明,这样选出的点,在仅保留与染色点相邻的边后,得到的图仍然是连通的

#include <bits/stdc++.h>
using namespace std;

#define int long long
const int N = 500005;

vector<int> g[N];
int n, m, u, v, fa[N], c[N];

void maketree(int p, int from)
{
    fa[p] = from;
    for (int q : g[p])
        if (fa[q] == 0)
            maketree(q, p);
}

void dfs(int p)
{
    int flag = 1;
    for (int q : g[p])
        if (c[q])
            flag = 0;
    if (flag)
        c[p] = 1;
    for (int q : g[p])
        if (fa[q] == p)
            dfs(q);
}

void solve()
{
    ios::sync_with_stdio(false);

    cin >> n >> m;
    for (int i = 1; i <= m; i++)
    {
        cin >> u >> v;
        g[u].push_back(v);
        g[v].push_back(u);
    }

    maketree(1, -1);
    dfs(1);

    int flag = 1;
    for (int i = 1; i <= n; i++)
        if (fa[i] == 0)
            flag = 0;
    if (flag)
    {
        cout << "YES" << endl;
        vector<int> ans;
        for (int i = 1; i <= n; i++)
            if (c[i])
                ans.push_back(i);
        cout << ans.size() << endl;
        for (int i : ans)
            cout << i << " ";
        cout << endl;
    }
    else
    {
        cout << "NO" << endl;
    }

    for (int i = 1; i <= n; i++)
        g[i].clear(), c[i] = 0, fa[i] = 0;
}

signed main()
{
    ios::sync_with_stdio(false);

    int t;
    cin >> t;
    while (t--)
    {
        solve();
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14382267.html