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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
#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;
}