Codeforces Round #600 (Div. 2) - D. Harmonious Graph(并查集)

题意:对于一张图,如果$a$与$b$连通,则对于任意的$c(a<c<b)$都有$a$与$c$连通,则称该图为和谐图,现在给你一张图,问你最少添加多少条边使图变为和谐图。

思路:将一个连通块内最大的点做为根,用并查集维护,遍历一遍,对于某个点$i$及该点连通块内的根$fx$,$i$到$fx$内的每一个点,当与$i$不属于一个集合时,进行合并,答案加一,同时更新该连通块的根。

#include <iostream>
#include <algorithm>
#include <cstdio>

using namespace std;

const int N = 200010;

int fa[N], n, m;

void init()
{
    for (int i = 1; i <= n; i++) fa[i] = i;
}

int find(int x)
{
    return x == fa[x] ? x : fa[x] = find(fa[x]);
}

void nuio(int x, int y)
{
    int fx = find(x), fy = find(y);
    if (fx != fy) {
        if (fx > fy) fa[fy] = fx;
        else fa[fx] = fy;
    }
}

int main()
{
    scanf("%d%d", &n, &m);
    init();
    for (int i = 1; i <= m; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        nuio(x, y);
    }
    int res = 0;
    for (int i = 1; i <= n; i++) {
        int fx = find(i);
        while (i < fx) {
            int fy = find(i);
            if (fx != fy) {
                res++;
                if (fx > fy) fa[fy] = fx;
                else fa[fx] = fy;
                fx = max(fx, fy);
            }
            i++;
        }
    }
    printf("%d\n", res);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/zzzzzzy/p/12034496.html