【转】并查集 - 检测图(无向图)是否包含环

转载:

https://www.geeksforgeeks.org/union-find/

并查集(1)-判断无向图是否存在环

 

并查集是一种树型的数据结构,用于处理一些不相交集合(Disjoint Sets)的合并及查询问题。常常在使用中以森林来表示。集就是让每个元素构成一个单元素的集合,也就是按一定顺序将属于同一组的元素所在的集合合并。

  • Find:确定元素属于哪一个子集。它可以被用来确定两个元素是否属于同一子集合。
  • Union:将两个子集合并成同一个集合。

其实判断一个图是否存在环已经有相应的算法,此文用并查集来判断一个图是否有环。

我们可以用一个一维数组parent[] 来记录子集合。

看下面这个图:

0
|  \
|    \
1-----2

对每一条边的两个顶点加入集合,发现两个相同的顶点在一个子集合中,就说明存在环。

初始化:parent[n] 的每个元素都为-1,共有n个子集合,表示集合只有当前顶点一个元素。

0 1 2
-1 -1 -1

然后逐个处理每条边。

边0-1:我们找到两个子集合 0 和1,因为他们在不同的子集合,现在需要合并他们(Union). 把其中一个子集合作为对方的父集合.

0   1   2    <----- 1 成为 0 的 父集合 (1 现在代表集合 {0, 1})
1  -1  -1

边0-2:1属于属于子集合1,2属于子集合2,因此合并他们。

0   1   2    <----- 2 作为 1的父集合 (2 现在代表集合 {0, 1, 2})
1   2  -1

 边0-2: 0是在子集和2和2也是在子集合2, 因为 0->1->2 // 1 是0 父集合 并且  2 是1的父集合 。因此,找到了环。

Python代码:

复制代码
 1 # Python Program for union-find algorithm to detect cycle in a undirected graph
 2 # we have one egde for any two vertex i.e 1-2 is either 1-2 or 2-1 but not both
 3   
 4 from collections import defaultdict
 5   
 6 #This class represents a undirected graph using adjacency list representation
 7 class Graph:
 8   
 9     def __init__(self,vertices):
10         self.V= vertices #No. of vertices
11         self.graph = defaultdict(list) # default dictionary to store graph
12   
13  
14     # function to add an edge to graph
15     def addEdge(self,u,v):
16         self.graph[u].append(v)
17   
18     # A utility function to find the subset of an element i
19     def find_parent(self, parent,i):
20         if parent[i] == -1:
21             return i
22         if parent[i]!= -1:
23              return self.find_parent(parent,parent[i])
24  
25     # A utility function to do union of two subsets
26     def union(self,parent,x,y):
27         x_set = self.find_parent(parent, x)
28         y_set = self.find_parent(parent, y)
29         parent[x_set] = y_set
30  
31   
32   
33     # The main function to check whether a given graph
34     # contains cycle or not
35     def isCyclic(self):
36          
37         # Allocate memory for creating V subsets and
38         # Initialize all subsets as single element sets
39         parent = [-1]*(self.V)
40  
41         # Iterate through all edges of graph, find subset of both
42         # vertices of every edge, if both subsets are same, then
43         # there is cycle in graph.
44         for i in self.graph:
45             for j in self.graph[i]:
46                 x = self.find_parent(parent, i) 
47                 y = self.find_parent(parent, j)
48                 if x == y:
49                     return True
50                 self.union(parent,x,y)
51  
52  
53 # Create a graph given in the above diagram
54 g = Graph(3)
55 g.addEdge(0, 1)
56 g.addEdge(1, 2)
57 g.addEdge(2, 0)
58  
59 if g.isCyclic():
60     print "Graph contains cycle"
61 else :
62     print "Graph does not contain cycle "
63   
64 #This code is contributed by Neelam Yadav
复制代码

 

posted @   Asp1rant  阅读(231)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示