CF 1253D-Harmonious Graph-並查集+貪心

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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章