HNUCM 并查集的简单应用

本文通过两个实例详细介绍了并查集在判断有向图是否存在环及构建最小连通图问题中的应用。在第一个例子中,通过并查集判断XP学长在随机漫步中是否会重复访问建筑;第二个例子中,利用并查集解决X星大学新校区光纤连接的最低成本问题。代码实现清晰,帮助理解并查集在实际问题中的运用。
摘要由CSDN通过智能技术生成

目前我所用到的并查集的题目主要是在判断是否有环存在与最小联通图上面,下面来看一下例题吧。

判断是否有环存在

众所周知,XP学长即将毕业了,所以他觉得在校园里来一次漫步,在学校中有N个标志性的建筑,XP学长并不喜欢走小路,因此他会随机的选择某条大路从某个建筑走到另一个建筑,XP学长当然想要走遍校园内的所有建筑,但他会随机的选择某一条路去漫步,当然XP学长走完某一条路,绝对不会走这一条路,也就是说,如果XP学长当前所在建筑为v,他选择走v->u的某一条大路e,到达u建筑后,他在之后的漫步里不会再选择这条路,但是这仍然可能导致他到达某个建筑两次,XP学长表示他不想观看同样的建筑两次,因此他想问问你,如果他随机的选择这些路去漫步,是否会出现到达一个建筑两次或两次以上的现象,当然了,XP学长可以选择任意的建筑作为他的起始点。

输入

输入包含多组测试用例,第一行输入一个T表示测试数据组数,(1<=T<=10),每组测试数据首先输入有两个整数N,M,N表示校园内有N个建筑(分别用1-N来标记它们),M表示校园内有M条大路,它们连接着这些建筑。(2<=N<=10^5,1<=M<=10^5),接下来M行每行两个整数u,v,表示u,v之间有一条大路(1<=u,v<=N),每条大路都是无向的,保证图中不出现自环现象,不保证图是连通的。

输出

如果XP学长随机漫步,会出现上述现象,请输出YES,否则输出NO。

样例输入 Copy

1
4 3
1 2
2 3
1 3

样例输出 Copy

YES

提示

在样例中,XP学长可以选择1作为他的起始建筑,那么他可能走这样的一条路径:1->2->3->1,此时XP学长到达了建筑1两次,因此你需要输出YES。

代码如下

#include<iostream>
#include<algorithm>
#include<map>
using namespace std;

int par[100005];
int get(int a){
	if (par[a] != a) {
		par[a] = get(par[a]);  //不断找父节点 
	} 
	return par[a];
	
}


int merge(int u, int v) {
	int get_u = get(u);
	int get_v = get(v);
	if (get_u == get_v) {
		return 0;
	}
	par[get_v] = u;//加入集合
	return 1;
}
int main() {
	int t;
	while (cin >> t) {
		
		int n, m;
		while (t--) {
			cin >> n >> m;
			for (int i = 1; i <= n; i++) {
				par[i] = i;//赋值,本身就是父节点
			}
			int flag = 0;
			for (int i = 1; i <= m; i++) {
				int u, v;
				cin >> u >> v;
				if(merge(u,v)==0)
				{
					flag = 1;//如果flag等于1则表示存在环
				}
			}
			if (flag == 1)cout << "YES" << endl;
			if (flag == 0)cout << "NO" << endl;
		}
	}
	return 0;
}

接下来是最小连通图问题: 

X星大学新校区终于建成啦!
新校区一共有N栋教学楼和办公楼。现在需要用光纤把这N栋连接起来,保证任意两栋楼之间都有一条有线网络通讯链路。
已知任意两栋楼之间的直线距离(单位:千米)。为了降低成本,要求两栋楼之间都用直线光纤连接。
光纤的单位成本C已知(单位:X星币/千米),请问最少需要多少X星币才能保证任意两栋楼之间都有光纤直接或者间接相连?
注意:如果1号楼和2号楼相连,2号楼和3号楼相连,则1号楼和3号楼间接相连。

输入

单组输入。
第1行输入两个正整数N和C,分别表示楼栋的数量和光纤的单位成本(单位:X星币/千米),N<=100,C<=100。两者之间用英文空格隔开。
接下来N*(N-1)/2行,每行包含三个正整数,第1个正整数和第2个正整数表示楼栋的编号(从1开始一直到N),编号小的在前,编号大的在后,第3个正整数为两栋楼之间的直线距离(单位:千米)。

输出

输出最少需要多少X星币才能保证任意两栋楼之间都有光纤直接或者间接相连。

样例输入 Copy

3 10
1 2 5
1 3 6
2 3 7

样例输出 Copy

110

 代码如下:

#include<iostream>
#include<string>
#include<algorithm>
using namespace std;

struct node {
	int a;
	int b;
	int c;
}e[105];
int cmp(node x, node y) {
	return x.b < y.b;
}
int f[105];

int get(int k) {
	return f[k] == k ? k : get(f[k]);
}
int main() {
	int n, c;
	cin >> n>> c;
	int sum = 0;
	for (int i = 1; i <= n * (n - 1) / 2; i++) {
		cin >> e[i].a >> e[i].b >> e[i].c ;
	 }
	sort(e+1, e + (n * (n - 1) / 2)+1, cmp);
	for (int i = 1; i <= n * (n - 1) / 2; i++)
		f[i] = i;
	for (int i = 1; i <= n * (n - 1) / 2; i++) {
		int x = get(e[i].a);
		int y = get(e[i].b);
		if (x != y) {
			f[y] = x;
			sum = sum + e[i].c;
		}
		else continue;
	}
	cout << sum * c << endl;
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

H-rosy

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值