算法知识点———并查集

并查集是一种用于管理元素所属集合的数据结构,实现为一个森林,其中每棵树表示一个集合,树中的节点表示对应集合中的元素。并查集支持两种操作:

合并(Union):合并两个元素所属集合(合并对应的树)

查询(Find):查询某个元素所属集合(查询对应的树的根节点),这可以用于判断两个元素是否属于同一集合。

经典用法:利用并查集检测图中是否有环。

初始parent数组可以设置为下标,表示结点的父亲结点是自己。

然后当结点1和结点2有边的时候可以设置结点2的父亲结点是结点1.结点3的父结点是结点4,那么parent[3] = 4

然后如果1和3这条边想合并的时候只需要合并1的父结点和3的父结点即可,也就是1的父结点是4.这样01234都在一个集合里面,也就是说root[0] == root[2] 表示0和2是互通的。

下面是合并x节点和y节点的过程

第一步find_root函数找到x节点的根结点或者y节点的根结点

第二步uniin函数合并x节点和y节点

并查集合并的时候容易导致树倾斜,可以采用秩优化;

每次合并都把深度较小的集合合并在深度较大的集合下面 。这种技术被称为按秩合并
路径压缩 实际上是在找完根结点之后,在递归回来的时候顺便把路径上元素的父亲指针都指向根结点。

题目2:

判断ip是否有连通性,其中连通具有传递性;

输入描述:

第一行包含两个整数n和m,表示已知的IP地址数量和连通关系数量。

接下来n行,每行包含一个字符串和一个整数,表示一个IP地址和它的编号。

接下来m行,每行包含两个整数a和b,表示IP地址对应的编号a和b之间有连通关系。

接下来一行包含一个整数q,表示需要判断连通性的IP地址数量。

接下来q行,每行包含两个字符串,表示需要判断连通性的两个 IP地址。

输出描述

对于每个需要判断连通性的IP地址对,如果它们连通,则输出"Yes",否则输出"No"。

示例1

5 3

192.168.0.1 1

192.168.0.2 2

192.168.0.3 3

192.168.0.4 4

192.168.0.5 5

1 2

2 3

4 5

3

192.168.0.1 192.168.0.2

192.168.0.2 192.168.0.3

192.168.0.3 192.168.0.4

输出:

Yes

Yes

No

cpp 复制代码
#include <iostream>
#include <unordered_map>
#include <string>
#include <vector>

using namespace std;

// 并查集类
class UnionFind {
public:
	UnionFind(int n) {
		parent.resize(n + 1);
		rank.resize(n + 1, 0);
		for (int i = 1; i <= n; ++i) {
			parent[i] = i;
		}
	}

	// 查找集合的根节点,路径压缩优化
	int find(int x) {
		if (parent[x] != x) {
			parent[x] = find(parent[x]);
		}
		return parent[x];
	}

	// 合并两个集合,按秩合并优化
	void unite(int x, int y) {
		int rootX = find(x);
		int rootY = find(y);
		if (rootX != rootY) {
			if (rank[rootX] > rank[rootY]) {
				parent[rootY] = rootX;
			}
			else if (rank[rootX] < rank[rootY]) {
				parent[rootX] = rootY;
			}
			else {
				parent[rootY] = rootX;
				rank[rootX]++;
			}
		}
	}

private:
	vector<int> parent; // 父节点数组
	vector<int> rank;   // 秩数组 记录每个集合的"秩"或"高度"。
};

int main() {
	int n, m;
	cin >> n >> m;

	unordered_map<string, int> ipMap; // IP地址到编号的映射
	string ip;
	int id;

	// 输入n个IP地址和对应的编号
	for (int i = 0; i < n; ++i) {
		cin >> ip >> id;
		ipMap[ip] = id;
	}

	// 初始化并查集
	UnionFind uf(n);

	int a, b;
	// 输入m个连通关系
	for (int i = 0; i < m; ++i) {
		cin >> a >> b;
		uf.unite(a, b); // 将a和b所属的集合合并
	}

	int q;
	cin >> q;
	string ip1, ip2;

	// 对每个查询判断是否连通
	for (int i = 0; i < q; ++i) {
		cin >> ip1 >> ip2;
		if (uf.find(ipMap[ip1]) == uf.find(ipMap[ip2])) {
			cout << "Yes" << endl;
		}
		else {
			cout << "No" << endl;
		}
	}

	return 0;
}
相关推荐
hie9889412 分钟前
MATLAB锂离子电池伪二维(P2D)模型实现
人工智能·算法·matlab
杰克尼22 分钟前
BM5 合并k个已排序的链表
数据结构·算法·链表
.30-06Springfield1 小时前
决策树(Decision tree)算法详解(ID3、C4.5、CART)
人工智能·python·算法·决策树·机器学习
我不是哆啦A梦1 小时前
破解风电运维“百模大战”困局,机械版ChatGPT诞生?
运维·人工智能·python·算法·chatgpt
xiaolang_8616_wjl1 小时前
c++文字游戏_闯关打怪
开发语言·数据结构·c++·算法·c++20
small_wh1te_coder1 小时前
硬件嵌入式学习路线大总结(一):C语言与linux。内功心法——从入门到精通,彻底打通你的任督二脉!
linux·c语言·汇编·嵌入式硬件·算法·c
hqxstudying2 小时前
Java创建型模式---单例模式
java·数据结构·设计模式·代码规范
挺菜的2 小时前
【算法刷题记录(简单题)002】字符串字符匹配(java代码实现)
java·开发语言·算法
sun0077002 小时前
数据结构——栈的讲解(超详细)
数据结构
凌肖战5 小时前
力扣网编程55题:跳跃游戏之逆向思维
算法·leetcode