[CF9E] Interesting Graph and Apples

[CF9E] Interesting Graph and Apples - 构造,并查集

Description

给出 n 个点,m 条边,问是否能通过加一些边,使得 n 个点构成有且仅有 n 条边的单个环。如果能,输出 YES 以及加上的边的条数,并按字典序打印加上的边的两个端点。如果有多组解,输出字典序最小的一种方法。否则输出 NO 即可。

Solution

做法其实比较丰富,尽量去弄一个简单点不容易错的

先特判两种特殊情况:不需要加任何边(连通,所有点度数都是 2),没救(有点的度数大于 2,有自环)

剩下的情况一定可以构造出解

我们先枚举一个点 i,再枚举一个点 j,如果这两个点所在集合不连通,并且度数都小于 2,就连边

这样做一遍下来以后,一定可以串成一条链

显然不会出现度数大于 2 的点
对于每个 i,如果它和任何另一个 j 所在集合不连通,那么枚举到那个集合的链端时一定会连上一条边

最后,我们找到两个度数为 1 的点,连边,就完事了

(代码已经混乱不堪了)

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

#define int long long

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

    int n, m;
    cin >> n >> m;

    if (n == 1 && m == 0)
    {
        cout << "YES
1
1 1" << endl;
        return 0;
    }

    vector<int> fa(n + 2);
    for (int i = 1; i <= n; i++)
        fa[i] = i;

    vector<int> d(n + 2);

    function<int(int)> find = [&](int x) -> int {
        return x == fa[x] ? x : fa[x] = find(fa[x]);
    };

    function<void(int, int)> merge = [&](int x, int y) -> void {
        x = find(x);
        y = find(y);
        fa[x] = y;
    };

    int circle_flag = 0, self_circle = 0;

    for (int i = 1; i <= m; i++)
    {
        int u, v;
        cin >> u >> v;
        if (u == v)
            self_circle = 1;
        if (find(u) == find(v))
            circle_flag = 1;
        merge(u, v);
        d[u]++;
        d[v]++;
    }

    int min_deg = 1e9, max_deg = 0;
    for (int i = 1; i <= n; i++)
    {
        min_deg = min(min_deg, d[i]);
        max_deg = max(max_deg, d[i]);
    }
    if (max_deg > 2 || (self_circle && n > 1))
    {
        cout << "NO" << endl;
    }
    else if ((circle_flag && min_deg == 2 && max_deg == 2))
    {
        cout << "YES" << endl
             << 0 << endl;
    }
    else
    {
        vector<pair<int, int>> ans;
        for (int i = 1; i <= n; i++)
        {
            for (int j = 1; j <= n; j++)
                if (j != i)
                {
                    if (find(i) != find(j) && d[i] < 2 && d[j] < 2)
                    {
                        ans.push_back({min(i, j), max(i, j)});
                        d[i]++;
                        d[j]++;
                        merge(i, j);
                    }
                }
        }
        vector<int> tmp;
        for (int i = 1; i <= n; i++)
            if (d[i] < 2)
                tmp.push_back(i);
        ans.push_back({tmp[0], tmp[1]});
        int flag = 1;
        if (tmp.size() == 2)
        {
            d[tmp[0]]++;
            d[tmp[1]]++;
            for (int i = 1; i <= n; i++)
                if (d[i] != 2)
                    flag = 0;
        }
        else
        {
            flag = 0;
        }
        if (flag)
        {
            cout << "YES" << endl
                 << n - m << endl;
            for (auto [x, y] : ans)
                cout << x << " " << y << endl;
        }
        else
        {
            cout << "NO" << endl;
        }
    }
}
原文地址:https://www.cnblogs.com/mollnn/p/14406777.html