Description
You’re given an undirected graph with n nodes and m edges. Nodes are numbered from 1 to n.
The graph is considered harmonious if and only if the following property holds:
- For every triple of integers (l,m,r) such that 1≤l<m<r≤n, if there exists a path going from node l to node r, then there exists a path going from node l to node m.
In other words, in a harmonious graph, if from a node l
we can reach a node r through edges (l<r), then we should able to reach nodes (l+1),(l+2),…,(r−1) too.
What is the minimum number of edges we need to add to make the graph harmonious?
Input
The first line contains two integers n and m (3≤n≤200 000 and 1≤m≤200 000).
The i-th of the next m lines contains two integers ui and vi (1≤ui,vi≤n, ui≠vi), that mean that there’s an edge between nodes u and v.
It is guaranteed that the given graph is simple (there is no self-loop, and there is at most one edge between every pair of nodes).
Output
Print the minimum number of edges we have to add to the graph to make it harmonious.
Sample Input
14 8
1 2
2 7
3 4
6 3
5 7
3 8
6 8
11 12
Sample Output
1
核心思想:
並查集+貪心。此題集合的祖先是集合內結點的最大值。
n個在數值大小上相互交叉的集合是不獨立的,加n-1條邊後構成子圖。
子圖之間是相互獨立的,互不影響。
例如樣例:
集合有三個:
1,2,5,7
3,4,6,8
11,12
前兩個集合有交叉,加1條邊後構成一個子圖,第三個集合自己是一個子圖。
遍歷每個子圖,對於某個子圖:
將最小值的祖先充當子圖的祖先,作爲初始化。從小到大遍歷數值i,如果i和子圖的祖先在一個集合中,不需要處理,否則將i所在集合和子圖祖先所在集合合併,且更新子圖的祖先,ans+1。
詳見代碼!
代碼如下:
#include<cstdio>
#include<iostream>
using namespace std;
const int N=2e5+20;
int pre[N];
int find(int x)
{
if(pre[x]==x) return x;
return pre[x]=find(pre[x]);
}
void merge(int x,int y)
{
int fx=find(x),fy=find(y);
pre[fx]=pre[fy]=max(fx,fy);//祖先爲集合中結點的最大值
return;
}
int main()
{
int n,m,x,y,st=n,en=0,ans=0;//st爲最小值,en爲最大值
cin>>n>>m;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=0;i<m;i++)
{
scanf("%d%d",&x,&y);
merge(x,y);
st=min(st,min(x,y));
en=max(en,max(x,y));
}
while(st<=en)
{
int w=find(st);//w爲當前子圖的結點最大值
for(int i=st;i<=w;i++)
{
if(find(i)!=w)//結點i不在當前子圖中,加入
{
ans++;
merge(i,w);
w=max(w,find(i));//更新w
}
}
for(st=w+1;st<=en&&pre[st]==st;st++);//更換子圖,兩個子圖之間的數值無意義
}
printf("%d\n",ans);
return 0;
}