[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();
}
}