并查集练习题1:朋友圈

题目描述
​ 所谓一个朋友圈子,不一定其中的人都互相直接认识。

​ 例如:小张的朋友是小李,小李的朋友是小王,那么他们三个人属于一个朋友圈。

​ 现在给出一些人的朋友关系,人按照从 1 到 n 编号在这中间会进行询问某两个人是否属于一个朋友圈,请你编写程序,实现这个过程。

输入
第一行输入两个整数 n,m(1≤n≤10000,3≤m≤100000),分别代表人数和操作数。

接下来 m 行,每行三个整 a,b,c(a∈[1,2], 1≤b,c≤n)
当 a=1 时,代表新增一条已知信息,b,c 是朋友
当 a=2 时,代表根据以上信息,询问 b,c 是否是朋友
输出
对于每个 a=2 的操作,输出『Yes』或『No』代表询问的两个人是否是朋友关系。

样例输入

6 5
1 1 2
2 1 3
1 2 4
1 4 3
2 1 3

样例输出

No
Yes

数据规模与约定
时间限制:1 s

内存限制:64 M

100% 的数据保证n,m(1≤n≤10000,3≤m≤100000)

方法:
1.quick_find

#include <stdio.h>
#include <stdlib.h>

typedef struct UnionSet {
    
    
	int* color;
	int n;
}UnionSet;

UnionSet* init(int n) {
    
    
	UnionSet* u = (UnionSet*)malloc(sizeof(UnionSet));
	u->color = (int*)malloc(sizeof(int) * (n + 1));
	for (int i = 1; i <= n; i++) {
    
    
		u->color[i] = i;
	}
	u->n = n;
	return u;
}

int find(UnionSet* u, int x) {
    
    
	return u->color[x];
}

int merge(UnionSet* u, int a, int b) {
    
    
	if (find(u, a) == find(u, b)) return 0;
	int color_a = u->color[a];
	for (int i = 1; i <= u->n; i++) {
    
    
		if (u->color[i] - color_a) continue;
		u->color[i] = u->color[b];
	}
	return 1;
}

void clear(UnionSet* u) {
    
    
	if (u == NULL) return;
	free(u->color);
	free(u);
	return;
}

int main() {
    
    
	int n, m;
	scanf("%d%d", &n, &m);
	UnionSet* u = init(n);
	for (int i = 0; i < m; i++) {
    
    
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		switch (a) {
    
    
		case 1: merge(u, b, c); break;
		case 2:printf("%s\n", find(u, b) == find(u, c) ? "Yes" : "No"); break;
		}
	}
	clear(u);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

2.quick_union

#include <stdio.h>
#include <stdlib.h>

typedef struct UnionSet {
    
    
	int* father;
	int n;
}UnionSet;

UnionSet* init(int n) {
    
    
	UnionSet* u = (UnionSet*)malloc(sizeof(UnionSet));
	u->father = (int*)malloc(sizeof(int) * (n + 1));
	for (int i = 1; i <= n; i++) {
    
    
		u->father[i] = i;
	}
	u->n = n;
	return u;
}

int find(UnionSet* u, int x) {
    
    
	if (u->father[x] == x) return x;
	return find(u, u->father[x]);
}

int merge(UnionSet* u, int a, int b) {
    
    
	int fa =find(u, a), fb = find(u, b);
	if (fa == fb) return 0;
	u->father[fa] = fb;
	return 1;
}

void clear(UnionSet* u) {
    
    
	if (u == NULL) return;
	free(u->father);
	free(u);
	return;
}

int main() {
    
    
	int n, m;
	scanf("%d%d", &n, &m);
	UnionSet* u = init(n);
	for (int i = 0; i < m; i++) {
    
    
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		switch (a) {
    
    
		case 1: merge(u, b, c); break;
		case 2:printf("%s\n", find(u, b) == find(u, c) ? "Yes" : "No"); break;
		}
	}
	clear(u);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

  1. 优化1:weighted quick_union
#include <stdio.h>
#include <stdlib.h>

#define swap(a,b) {
      
      \
a ^= b,b ^= a, a ^= b;\
}
typedef struct UnionSet {
    
    
	int* father, *size;
	int n;
}UnionSet;

UnionSet* init(int n) {
    
    
	UnionSet* u = (UnionSet*)malloc(sizeof(UnionSet));
	u->father = (int*)malloc(sizeof(int) * (n + 1));
	u->size = (int*)malloc(sizeof(int) * (n + 1));
	for (int i = 1; i <= n; i++) {
    
    
		u->father[i] = i;
		u->size[i] = 1;
	}
	u->n = n;
	return u;
}

int find(UnionSet* u, int x) {
    
    
	if (u->father[x] == x) return x;
	return find(u, u->father[x]);
}

int merge(UnionSet* u, int a, int b) {
    
    
	int fa =find(u, a), fb = find(u, b);
	if (fa == fb) return 0;
	if (u->size[fa] < u->size[fb]) swap(fa, fb);
	u->father[fb] = fa;
	u->size[fa] += u->size[fb];
	return 1;
}

void clear(UnionSet* u) {
    
    
	if (u == NULL) return;
	free(u->father);
	free(u->size);
	free(u);
	return;
}

int main() {
    
    
	int n, m;
	scanf("%d%d", &n, &m);
	UnionSet* u = init(n);
	for (int i = 0; i < m; i++) {
    
    
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		switch (a) {
    
    
		case 1: merge(u, b, c); break;
		case 2:printf("%s\n", find(u, b) == find(u, c) ? "Yes" : "No"); break;
		}
	}
	clear(u);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

  1. 优化2: 路径压缩 + weighted quick_union
#include <stdio.h>
#include <stdlib.h>

#define swap(a,b) {
      
      \
a ^= b,b ^= a, a ^= b;\
}
typedef struct UnionSet {
    
    
	int* father, *size;
	int n;
}UnionSet;

UnionSet* init(int n) {
    
    
	UnionSet* u = (UnionSet*)malloc(sizeof(UnionSet));
	u->father = (int*)malloc(sizeof(int) * (n + 1));
	u->size = (int*)malloc(sizeof(int) * (n + 1));
	for (int i = 1; i <= n; i++) {
    
    
		u->father[i] = i;
		u->size[i] = 1;
	}
	u->n = n;
	return u;
}

int find(UnionSet* u, int x) {
    
    
	if (u->father[x] == x) return x;
	return u->father[x] = find(u, u->father[x]);
}

int merge(UnionSet* u, int a, int b) {
    
    
	int fa =find(u, a), fb = find(u, b);
	if (fa == fb) return 0;
	if (u->size[fa] < u->size[fb]) swap(fa, fb);
	u->father[fb] = fa;
	u->size[fa] += u->size[fb];
	return 1;
}

void clear(UnionSet* u) {
    
    
	if (u == NULL) return;
	free(u->father);
	free(u->size);
	free(u);
	return;
}

int main() {
    
    
	int n, m;
	scanf("%d%d", &n, &m);
	UnionSet* u = init(n);
	for (int i = 0; i < m; i++) {
    
    
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		switch (a) {
    
    
		case 1: merge(u, b, c); break;
		case 2:printf("%s\n", find(u, b) == find(u, c) ? "Yes" : "No"); break;
		}
	}
	clear(u);
	return 0;
}

在这里插入图片描述
在这里插入图片描述

  1. 优化3:路径压缩 quick_union
#include <stdio.h>
#include <stdlib.h>


typedef struct UnionSet {
    
    
	int* father;
	int n;
}UnionSet;

UnionSet* init(int n) {
    
    
	UnionSet* u = (UnionSet*)malloc(sizeof(UnionSet));
	u->father = (int*)malloc(sizeof(int) * (n + 1));
	for (int i = 1; i <= n; i++) {
    
    
		u->father[i] = i;
	}
	u->n = n;
	return u;
}

int find(UnionSet* u, int x) {
    
    
	if (u->father[x] == x) return x;
	return u->father[x] = find(u, u->father[x]);
}

int merge(UnionSet* u, int a, int b) {
    
    
	int fa =find(u, a), fb = find(u, b);
	if (fa == fb) return 0;
	u->father[fb] = fa;
	return 1;
}

void clear(UnionSet* u) {
    
    
	if (u == NULL) return;
	free(u->father);
	free(u);
	return;
}

int main() {
    
    
	int n, m;
	scanf("%d%d", &n, &m);
	UnionSet* u = init(n);
	for (int i = 0; i < m; i++) {
    
    
		int a, b, c;
		scanf("%d%d%d", &a, &b, &c);
		switch (a) {
    
    
		case 1: merge(u, b, c); break;
		case 2:printf("%s\n", find(u, b) == find(u, c) ? "Yes" : "No"); break;
		}
	}
	clear(u);
	return 0;
}

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_40713201/article/details/125395933