图论-并查集

**并查集(Union-find Sets)**是一种非常精巧而实用的数据结构,它主要用于处理一些不相交集合的合并问题.一些常见的用途有求连通子图,求最小生成树Kruskal算法和最近公共祖先(LCA)等.

并查集的基本操作主要有:

.1.初始化

2.查询find

3.合并union

一般我们都会采用路径压缩 这样效率更加高

cpp 复制代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
#define MAXN 20001
int fa[MAXN];
void init(int n) {
	for (int i = 1; i <= n; i++) {
		fa[i] = i;
	}//初始化
}
int find(int x) {
	if (x == fa[x]) {
		return x;

	}
	else {
		fa[x] = find(fa[x]);//路径压缩 也就是一直找到祖先
		return fa[x];
	}
}
void unionn(int i, int j) {
	int i_fa = find(i);//找到i的祖先
	int j_fa = find(j);//找到j的祖先
	fa[i_fa] = j_fa;//i的祖先指向j的祖先 反过来也可以
}
int main() {
	int n, m, x, y, q;
	scanf("%d", &n);
	init(n);
	scanf("%d", &m);
	for (int i = 1; i <= m; i++) {
		scanf("%d%d", &x, &y);
		unionn(x, y);
	}
	scanf("%d", &q);
	for (int i = 1; i <= q; i++) {
		scanf("%d%d", &x, &y);
		if (find(x) == find(y)) {
			printf("Yes\n");
		}
		else {
			printf("No\n");
		}

	}


	return 0;
}

或者这样写

cpp 复制代码
#include<iostream>
#include<cstring>
#include<algorithm>

using namespace std;

const int N = 20010;

int n, m;
int p[N];
int find(int x) {
	if (p[x] != x)p[x] = find(p[x]);
	return p[x];
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) p[i] = i;
	while (m--) {
		int a, b;
		scanf("%d%d", &a, &b);
		p[find(a)] = find(b);//合并 a->b
	}
	scanf("%d,&m");
	while (m--) {

		int a, b;
		scanf("%d%d", &a, &b);
		if (find(a) == find(b))puts("yes");
		else puts("no");
	}
	return 0;
	
}
cpp 复制代码
#include<iostream>
using namespace std;

const int N = 10010;

int n, m;
int p[N];

int find(int x) {
	if (p[x] != x)p[x] = find(p[x]);
	return p[x];
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) p[i] = i;
	char op[2];//读入操作的字符串  因为字符串后面有'\0'所以要存多一位
	while (m--) {
		int a, b;
		scanf("%s%d%d",&op ,&a, &b);
		if(*op=='M')p[find(a)] = find(b);//合并
		else {
			if (find(a) == find(b)) {
				puts("Yes");
			}
			else {
				puts("No");
			}
		}

	}

	return 0;
}

cpp 复制代码
#include<iostream>
using namespace std;
const int N = 10010;

int n, m;
int p[N], s[N];

int find(int x) {
	if (p[x] != x)p[x] = find(p[x]);
	return p[x];
}
int main() {
	scanf("%d%d", &n, &m);
	for (int i = 1; i <= n; i++) p[i] = i, s[i] = 1;
	while (m--)
	{
		char op[3];
		int a, b;
		scanf("%s", &op);
		if (*op == 'C') {
			scanf("%d%d", &a, &b);
			a = find(a), b = find(b);
			if (a != b) {//如果相等证明他们在同一个祖先中
				s[b] += s[a];
				p[a] = b;
			}
			else if (*op == 'Q1') {
				scanf("%d%d", &a, &b);
				if (find(a) == find(b)) {
					puts("Yes\n");
				}
				else {
					puts("No\n");
				}
			}
			else {
				scanf("%d", &a);
				printf("%d\n", s[find(a)]);
			}
		}
	}
	return 0;
}
相关推荐
依然鸣1 天前
PTA团体程序设计天梯赛L2真题讲解L2-005-008
开发语言·数据结构·c++·算法·深度优先·pat考试·图论
wabs6662 天前
关于图论【最短路径之Bellman_ford 算法(单源有限最短路)|卡码网96.城市间货物运输III的思考】
数据结构·算法·图论·卡码网·bellman_ford·单源有限最短路
wabs6663 天前
关于图论【最短路径之Bellman_ford 算法(判断负权回路)|卡码网95.城市间货物运输II的思考】
数据结构·算法·图论·bellman_ford算法·卡码网·判断负权回路
cpp_25014 天前
P1113 [USACO02FEB] 杂务
数据结构·c++·算法·动态规划·图论·拓扑排序·洛谷题解
漂流瓶jz4 天前
UVA-12174 Shuffle的播放记录 题解答案代码 算法竞赛入门经典第二版
数据结构·c++·算法·图论·滑动窗口·算法竞赛入门经典·uva
wabs6665 天前
关于图论【最短路径之Bellman_ford 算法|卡码网94.城市间货物运输的思考】
数据结构·算法·图论·卡码网·bellman_ford·求最短路径
wabs6666 天前
关于图论【最短路径之Dijkstra算法(堆优化版)|卡码网47.参加科学大会的思考】
数据结构·算法·图论·优先级队列·邻接表·小顶堆·卡码网
wabs6666 天前
关于哈希表【力扣1.两数之和的思考】
数据结构·算法·leetcode·散列表·图论
oier_Asad.Chen7 天前
【洛谷题解/AcWing题解/真题】洛谷P2330【SCOI2005】繁忙的都市(Kruskal算法的再探究))
c++·算法·贪心算法·图论·最小生成树·kruskal
wabs6668 天前
关于图论【卡码网117.软件构建的思考】
数据结构·算法·软件构建·图论·卡码网