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

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

链接:Harmonious Graph
在这里插入图片描述
题意:给你 n n 个顶点, m m 条边,让你添加 a n s ans 条边把 n n 个点连成任意个连通块,要求每个连通块的顶点是一个连续的区间,即题目中所说 [ l , r ] [l,r] ,求 a n s ans 的最小值。
题解:显然这是一个并查集可以处理的问题,但是并查集怎么处理呢?建立一个父节点值大于子节点值得并查集,那么一个连通块里,根节点的值最大,那么我们就从连通块里最小的那个值依次遍历到最大的那个值,判断这些结点是否在一个集合里,如果不在,将其加入根节点的集合,此时 a n s + + ans++ ,直至最后一个连通块遍历完成。

代码:

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
const int maxn = 2e5+100;
int fa[maxn];
void init(int n)
{
    for(int i = 0; i <= n; i++)
    {
        fa[i] = i;
    }
}
int Find(int x)
{
    if(x==fa[x])
        return x;
    return fa[x] = Find(fa[x]);
}
int unite(int x,int y)
{
    x = Find(x);
    y = Find(y);
    if(x==y)
    {
        return 0;
    }
    if(x<y)
        fa[x] = y;
    else
        fa[y] = x;
    return 1;
}

int main()
{
    int n,m;
    scanf("%d%d", &n, &m);
    init(n);
    int x,y;
    for(int i = 0; i < m; i++)
    {
        scanf("%d%d", &x, &y);
        unite(x,y);//先合并,建立连通块
    }
    x = 0;
    int ans = 0;
    for(int i = 1; i <= n; i++)
    {
        y = Find(i);//找到i结点的父节点
        x = max(x,y);
        if(unite(x,y))//判断这两个结点时候在一个集合里,如果不在,则合并,同时ans++
        {
            ans++;
        }
    }
    printf("%d\n", ans);
    return 0;
}
发布了27 篇原创文章 · 获赞 13 · 访问量 1699

猜你喜欢

转载自blog.csdn.net/weixin_43855330/article/details/103262591