Codeforces Round #600 (Div. 2) D. Harmonious Graph 并查集
链接:Harmonious Graph
题意:给你
个顶点,
条边,让你添加
条边把
个点连成任意个连通块,要求每个连通块的顶点是一个连续的区间,即题目中所说
,求
的最小值。
题解:显然这是一个并查集可以处理的问题,但是并查集怎么处理呢?建立一个父节点值大于子节点值得并查集,那么一个连通块里,根节点的值最大,那么我们就从连通块里最小的那个值依次遍历到最大的那个值,判断这些结点是否在一个集合里,如果不在,将其加入根节点的集合,此时
,直至最后一个连通块遍历完成。
代码:
#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;
}