首页 > 技术文章 > 并查集

william4s 2020-10-10 00:02 原文

[并查集 ]

【引入】并查集是啥?

并查集真的是很简洁而又优雅的数据结构,主要用于解决一些元素分组的问题。它管理一系列不相交的集合,并支持两种操作:

  • 合并(Union):把两个不相交的集合合并为一个集合。
  • 查询(Find):查询两个元素是否在同一个集合中。

路径压缩可以将树的多层结构简化成1对多

在查询两个元素是否同一组时并不需要一层层上级查找,而是直接找每个人的BOSS

题目链接#

A. 畅通工程

思路:

题目要问最少还需要建设多少条道路?

将城镇群分组,能有路到达的城镇为一组

那么需要再建造的路为城镇组的个数-1

#include<bits/stdc++.h>  //黑夜给了我黑色的双眼
using namespace std;    //而我却用他来寻找光明
const int INF=0x3f3f3f3f;//2020.10.9 23:59
typedef long long ll;
int  pre[1050];
bool t[1050];
int Find(int x) //查询他的BOSS 
{
	int r=x;
	while(r!=pre[r])
		r=pre[r];

	int i=x,j;
	while(pre[i]!=r)
	{
		j=pre[i];
		pre[i]=r;
		i=j;
	}
	return r;
}

void mix(int x,int y) //join in
{
	int fx=Find(x),fy=Find(y);
	if(fx!=fy)
	{
		pre[fy]=fx;
	}
}

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	int N,M,a,b,i,j,ans;

	while(cin>>N>>M)
	{

		for(i=1; i<=N; i++)        //初始化,每个人的上级都是自己 
			pre[i]=i;

		for(i=1; i<=M; i++)        //将两个城镇联通 
		{
			cin>>a>>b;
			mix(a,b);
		}


		memset(t,0,sizeof(t));
		for(i=1; i<=N; i++)        //标记根结点
		{
			t[Find(i)]=1;
		}
		for(ans=0,i=1; i<=N; i++)
			if(t[i])
				ans++;

		cout<<ans-1<<"\n";
	}


	return 0;
}




推荐阅读