题意:对于一张图,如果$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 ", res); return 0; }