欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 新闻 > 资讯 > 代码随想录第五十五天

代码随想录第五十五天

2024/12/22 2:08:25 来源:https://blog.csdn.net/2301_80630236/article/details/144343027  浏览:    关键词:代码随想录第五十五天

并查集理论基础

并查集的本质是一种维护不相交集合的数据结构。其核心思想是用树形结构来表示集合,每个集合是一棵树。

基本概念

  • 并查集维护了一个由不同元素构成的不相交集合
  • 每个集合用一棵树来表示,树的根节点是该集合的代表元素
  • 同一棵树中的所有节点属于同一个集合

核心操作 Find操作:

  • 功能:查找元素所在集合的代表元素(根节点)
  • 实现:从当前节点不断往上查找父节点,直到找到根节点

Union操作:

  • 功能:合并两个集合
  • 实现:将一个集合的根节点指向另一个集合的根节点

优化策略

1.路径压缩(Path Compression):

  • 在执行find操作时,将搜索路径上的所有节点直接连接到根节点
  • 显著减少树的高度,提高后续操作效率

按秩合并(Union by Rank):

  • 记录每棵树的高度(秩)
  • 总是将较矮的树挂在较高的树下面
  • 可以保证树的高度不会无限增长

代码模板:

#include <stdio.h>#define N 10001  // 根据实际问题调整大小int p[N];    // 父节点数组
int rank[N]; // 秩数组,用于按秩合并// 初始化
void init(int n) {for(int i = 0; i < n; i++) {p[i] = i;      // 每个节点的父节点初始化为自己rank[i] = 1;   // 初始的秩都为1}
}// 查找根节点(路径压缩)
int find(int x) {if(p[x] != x) p[x] = find(p[x]);return p[x];
}// 合并(按秩合并)
void unite(int x, int y) {x = find(x);y = find(y);if(x == y) return;if(rank[x] < rank[y]) {p[x] = y;} else {p[y] = x;if(rank[x] == rank[y]) rank[x]++;}
}// 判断是否连通
int same(int x, int y) {return find(x) == find(y);
}// 使用示例
int main() {int n = 10;  // 假设有10个节点init(n);// 合并一些集合unite(1, 2);unite(2, 3);unite(4, 5);// 判断连通性printf("%d\n", same(1, 3));  // 输出1,表示1和3连通printf("%d\n", same(1, 4));  // 输出0,表示1和4不连通return 0;
}

107.寻找存在的路径

题目描述

给定一个包含 n 个节点的无向图中,节点编号从 1 到 n (含 1 和 n )。

你的任务是判断是否有一条从节点 source 出发到节点 destination 的路径存在。

输入描述

第一行包含两个正整数 N 和 M,N 代表节点的个数,M 代表边的个数。

后续 M 行,每行两个正整数 s 和 t,代表从节点 s 与节点 t 之间有一条边。

最后一行包含两个正整数,代表起始节点 source 和目标节点 destination。

输出描述

输出一个整数,代表是否存在从节点 source 到节点 destination 的路径。如果存在,输出 1;否则,输出 0。

输入示例

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

输出示例

1

提示信息

数据范围:

1 <= M, N <= 100。

思路:

这道题直接用上面的思想就能解决,没有什么过多的思路,但是对于并查集还是要认真学习。

解答:

#include <stdio.h>
#include <stdbool.h>
#define NUM 1000
int P[NUM];
void init(int n)
{for(int i = 0;i < n;i++){P[i] = i;}
}
int find(int x)
{if(P[x] != x)P[x] = find(P[x]);return P[x];
}
bool issame(int x,int y)
{return find(x) == find(y);
}
void unite(int x, int y) {P[find(x)] = find(y);
}
int main()
{int N,M;scanf("%d %d",&N,&M);init(N);for(int i = 0;i < M;i++){int s,t;scanf("%d %d",&s,&t);unite(s,t);}int source,destination;scanf("%d %d",&source,&destination);if(issame(source,destination)){printf("1");}else{printf("0");   }
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com