[CF25D] Roads not only in Berland - 并查集
Description
给定一个 n 个顶点,n-1 条边的无向图,每次操作去掉一条边,并在两个顶点之间重新连边,需要多少次操作使得从任一顶点都能到达其它所有顶点。构造方案。
Solution
任意求生成树,找出所有的非树边,记为集合 Sd
将所有与 1 点不连通的点找出来,记为集合 Sa
Sd 和 Sa 中的元素随意配对即可
#include <bits/stdc++.h>
using namespace std;
#define int long long
signed main()
{
ios::sync_with_stdio(false);
int n;
cin >> n;
vector<int> fa(n + 2);
for (int i = 1; i <= n; i++)
fa[i] = i;
function<int(int)> find = [&](int x) -> int {
return x == fa[x] ? x : fa[x] = find(fa[x]);
};
vector<pair<int, int>> sa, sd;
for (int i = 1; i < n; i++)
{
int x, y;
cin >> x >> y;
if (find(x) != find(y))
fa[find(x)] = find(y);
else
sd.push_back({x, y});
}
for (int i = 2; i <= n; i++)
{
if (find(1) != find(i))
sa.push_back({1, find(i)}), fa[find(i)] = find(1);
}
cout << sa.size() << endl;
for (int i = 0; i < sa.size(); i++)
{
cout << sd[i].first << " " << sd[i].second << " " << sa[i].first << " " << sa[i].second << endl;
}
}