[CF25D] Roads not only in Berland

[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;
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14403748.html