你会得到一个有n个节点和m条边的无向图。节点的编号从1到n。
当且仅当以下属性成立时,该图被认为是和谐的。
对于每一个整数(l,m,r)的三重,使1≤l<m<r≤n,如果存在一条从节点l到节点r的路径,那么就存在一条从节点l到节点m的路径。
换句话说,在一个和谐图中,如果从一个节点l可以通过边(l<r)到达一个节点r,那么我们也应该能够到达节点(l+1),(l+2),...,(r-1)。
我们需要增加多少条边才能使图形和谐?
输入
第一行包含两个整数n和m(3≤n≤200 000和1≤m≤200 000)。
接下来的m行中的第i行包含两个整数ui和vi(1≤ui,vi≤n, ui≠vi),这意味着节点u和v之间有一条边。
保证给定的图是简单的(没有自循环,每对节点之间最多只有一条边)。
输出
打印我们必须添加到图中的最小数量的边,以使其和谐。
例子
inputCopy
14 8
1 2
2 7
3 4
6 3
5 7
3 8
6 8
11 12
输出拷贝
1
输入拷贝
200000 3
7 9
9 8
4 5
输出拷贝
0
注意
在第一个例子中,给定的图是不和谐的(例如,1<6<7,节点1可以通过路径1→2→7到达节点7,但节点1不能到达节点6)。然而,添加边(2,4)就足以使其和谐。
在第二个例子中,给定的图已经是和谐的。
让小的点的父节点为大的
遍历1~n找i的父节x;在i~x中若有父节点y大于x则,交换x与y的值,f[y] = x,同时变成i~x(y);
#include<iostream>
using namespace std;
int f[200050];
int find(int x)
{
if(f[x]==x)
return x;
else
return f[x]=find(f[x]);
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i = 1 ;i <= n;i ++)
{
f[i] = i;
}
for(int i = 1 ;i <= m;i ++)
{
int l,r;
scanf("%d %d",&l,&r);
int x = find(l);
int y = find(r);
if( x < y)
swap(x,y);
f[y] = x;
}
int ans = 0;
for(int i = 1 ;i <= n;i++)
{
int x=find(i);
while(i < x)
{
int y = find(i);
if(y != x)
{
if(x < y)
swap(x,y);
f[y] = x;
ans++;
}
i++;
}
}
printf("%d",ans);
}