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;
}
发布了144 篇原创文章 · 获赞 135 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/Nothing_but_Fight/article/details/103179503