题目链接:
大致题意:
给你n个点,m条边的无向图,求最少添加几条边满足要求:
节点 l 可以访问到节点 r,那么节点 l 也要能够访问 l+1,l+2…r-1,r。
例如 1可访问 4,那么又要满足可访问 2,3。
解题报告:
对于每一个连通块维护成节点最大值,我们可以从该连通块中节点最小值遍历到所维护的值,若发现不是同一连通块那么就要合并,同时更新连通块维护的最大值,当遍历完后说明小于维护值得均完成,直接更新访问起点。(较大的剪枝)
#define first f
#define second s
#define ll long long
#define mp make_pair
#define pb push_back
#define pf push_front
#define lb lower_bound
#define ub upper_bound
#include <bits/stdc++.h>
#define pii pair<string,string>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MOD=1e9+7;
const int inf=1e9+7;
const int maxn=1e6+5;
const double eps=1e-6;
const double PI=acos(-1.0);
const double e=2.718281828459;
int f[maxn];
int getfind(int x)
{
return x==f[x]?x:f[x]=getfind(f[x]);
}
void Merge(int x,int y)
{
x=getfind(x);y=getfind(y);
f[min(x,y)]=max(x,y);
}
int main()
{
int n,m,u,v;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)f[i]=i;
for(int i=1;i<=m;i++)scanf("%d%d",&u,&v),Merge(u,v);
int ans=0,j=1,i=1;
for(;i<=n;){
int k=getfind(i);
for(;j<=k;j++){
if(getfind(j)!=getfind(i))Merge(j,k),k=getfind(k),ans++;
}
i=k+1;j=k+1;
}
printf("%d\n",ans);
return 0;
}