热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

如何使用UnionFind算法检测无定向图中的周期

如何使用UnionFind算法检测无定向图中的周期-在这篇文章中,我们探讨了使用union-find算法检测无向图中的循环的方法。这需要O(VE)的时间复杂度:目录

在这篇文章中,我们探讨了使用union-find算法检测无向图中的循环的方法。这需要O(VE)的时间复杂度:

目录
1)联合查找算法概述
2)简介
3)使用Union-Find算法查找周期的算法
4)通过例子理解算法
5)在Python中的实现
6)结论

1)联合查找算法概述

Disjoint-Set是用于Union-Find算法的数据结构。

Disjoint-Set的定义如下:

给定一个元素集。这些项目被划分为几个子集,使每个元素被限制在一个特定的子集中。

简单来说,Disjoint-Set数据结构是一组集合,其中没有两个集合包含相同的元素。

它也被称为联合-查找数据结构,因为它支持对子集的联合和查找操作。我们来理解这些术语。

查找:每个子集由该子集的一个元素代表,称为集合代表。该操作返回它所属的特定元素的集合代表。这个操作的最坏情况下的时间复杂度为 O(N)其中N是集合中的元素数,因为它是递归地找到集合代表的。

Union:在这个操作中,两个子集被合并为一个子集,合并后的子集的集合代表将是那些被合并的子集的集合代表中的一个。这个操作的时间复杂度为 O(1).

还有一个操作叫做make-set操作。

Mak-Set:这个操作为给定集合中的每个元素创建不相交的集合,每个不相交集合的集合代表将是其中包含的元素。这个操作的时间复杂度为 O(1).

这里每个子集都可以被称为不相交集。

2)简介

简单地说,如果存在一条起始顶点和结束顶点相同的路径,那么这个图就被称为循环图。

考虑一下路径:

1-2-3-4-5-1

开始和结束的顶点是相同的。因此,该图包含循环。

3)使用Union-Find找到循环的算法

对图中的每条边(u,v)重复以下步骤-如果u和v都属于同一个互不相干的集合,则图中存在循环

4)通过例子理解算法

让我们使用联合查找算法来查找无向图中的循环。

找出图中的边:

*1-2
2-3 3
-4 3-
6
4-5
1-5

由于有六个顶点,我们将创建六个不相交的集合:

集合 元素 集合代表
S1 {1} 1
S2 {2} 2
S3 {3} 3
S4 {4} 4
S5 {5} 5
S6 {6} 6

考虑边1-2:

find(1)=1
find(2)=2

UNION(1,2)

S1,S2将被合并到S1,S1的集合代表现在是1:

设置 元素 集合代表
S1 {1,2} 1
S3 {3} 3
S4 {4} 4
S5 {5} 5
S6 {6} 6

考虑边2-3:

find(2)=1
find(3)=3

UNION(1,3)

S1,S3将被合并到S1,S1的集合代表现在是1:

设置 元素 集合代表
S1 {1,2,3} 1
S4 {4} 4
S5 {5} 5
S6 {6} 6

考虑边3-4:

find(3)=1
find(4)=4

UNION(1,4)

S1,S4将被合并到S1,S1的集合代表现在是1。

设置 元素 集合代表
S1 {1,2,3,4} 1
S5 {5} 5
S6 {6} 6

考虑边3-6:

find(3)=1
find(6)=6

UNION(1,6)

S1,S6将被合并到S1,S1的集合代表现在是1:

集合 元素 集合代表
S1 {1,2,3,4,6} 1
S5 {5} 5

考虑边4-5:

find(4)=1
find(5)=5

调用union(1,5)

S1,S5将被合并到S1,S1的集合代表现在是1:

设置 元素 集合代表
S1 {1,2,3,4,5,6} 1

考虑边1-5:

find(1)=1
find(5)=1

这里FIND(1)=FIND(5),意味着两者都属于同一个不相交的集合。因此,该图有一个循环:

5)用Python实现

class Union_Find:
    def make_set(self,n):
        self.disjoint_set={vertex:vertex for vertex in range(1,n+1)}#Initializing n subsets and make contained vertex itself the set-representative for each subset
    def find(self,vertex):
        if self.disjoint_set[vertex]==vertex:#A set-representative can be found if v:v
            return vertex
        return self.find(self.disjoint_set[vertex])
    def union(self,x,y):
        set_representative_X=self.find(x)#find set-representative of x
        set_representative_Y=self.find(y)#find set-representative of y
        self.disjoint_set[set_representative_Y]=set_representative_X#make set-representative of y as x

def isCyclic(edges,no_of_vertices):
    ds=Union_Find()
    ds.make_set(no_of_vertices)
    for x,y in edges:
        if ds.find(x)==ds.find(y):#if set-representatives of both the vertices are the same then cycle exists
            print("Cycle exists in the graph!")
            return
        ds.union(x,y)#merge subsets x and y
    print("Cycle doesn't exist in the graph!")
V=int(input())
E=int(input())
edges=[]
for t in range(E):
    x,y=[int(x) for x in input().split()]
    edges.append([x,y])
isCyclic(edges,V)

输入:

V=6
E=6
edges=[[1,2],[2,3],[3,4],[3,6],[4,5],[1,5]]

输出:

Cycle exists in the graph!

考虑不包含循环的图形:

输入: 输出: 考虑不包含循环的图:

V=6
E=6
edges=[[1,4],[2,5],[3,6]]

输出:

Cycle doesn't exist in the graph!

6)结论

联合查找算法的时间复杂度为 O(V),其中V是图中的顶点数量,在最坏的情况下。

由于我们需要访问每条边,所以需要的时间为 O(E)其中E是图中的边的数量。

因此,使用Union-Find检测无定向图中的周期的总体时间复杂度为 O(VE).

在这种情况下,V是顶点的数量,E是边的数量。在密集图的情况下,E的数量为O(V2)。因此,在密集图中,这种方法需要O(V3)的时间复杂度。

通过OpenGenus的这篇文章,你一定对如何使用Union Find算法检测无定向图中的周期有了完整的认识。


推荐阅读
  • 超级简单加解密工具的方案和功能
    本文介绍了一个超级简单的加解密工具的方案和功能。该工具可以读取文件头,并根据特定长度进行加密,加密后将加密部分写入源文件。同时,该工具也支持解密操作。加密和解密过程是可逆的。本文还提到了一些相关的功能和使用方法,并给出了Python代码示例。 ... [详细]
  • 本文介绍了在处理不规则数据时如何使用Python自动提取文本中的时间日期,包括使用dateutil.parser模块统一日期字符串格式和使用datefinder模块提取日期。同时,还介绍了一段使用正则表达式的代码,可以支持中文日期和一些特殊的时间识别,例如'2012年12月12日'、'3小时前'、'在2012/12/13哈哈'等。 ... [详细]
  • 十大经典排序算法动图演示+Python实现
    本文介绍了十大经典排序算法的原理、演示和Python实现。排序算法分为内部排序和外部排序,常见的内部排序算法有插入排序、希尔排序、选择排序、冒泡排序、归并排序、快速排序、堆排序、基数排序等。文章还解释了时间复杂度和稳定性的概念,并提供了相关的名词解释。 ... [详细]
  • 本文介绍了一个Python函数same_set,用于判断两个相等长度的数组是否包含相同的元素。函数会忽略元素的顺序和重复次数,如果两个数组包含相同的元素,则返回1,否则返回0。文章还提供了函数的具体实现代码和样例输入输出。 ... [详细]
  • 颜色迁移(reinhard VS welsh)
    不要谈什么天分,运气,你需要的是一个截稿日,以及一个不交稿就能打爆你狗头的人,然后你就会被自己的才华吓到。------ ... [详细]
  • 第八章 元组与集合
    目录​一、元组二、集合三、集合的数学操作四、集合的相关操作五、集合间的关系六、列表、元组、集合、字典区别一、元组元组是python内置的数据结构之一, ... [详细]
  • 一.元祖类型 (tuple)1.什么是元祖?用途:用于存放多个值,当存放的多个值只有读的需求没有改变的需求时,用元祖最合适.定义方式:在()内用逗号分隔开的多个任意类型的值t(1, ... [详细]
  • 集合set集合是可变的容器集合内的数据对象都是唯一的(不能重复多次的)集合是无序的存储结构,集合中的数据没有先后关系集合内的元素必须是不可 ... [详细]
  • 我正在尝试使用 ... [详细]
  • 提升Python编程效率的十点建议
    本文介绍了提升Python编程效率的十点建议,包括不使用分号、选择合适的代码编辑器、遵循Python代码规范等。这些建议可以帮助开发者节省时间,提高编程效率。同时,还提供了相关参考链接供读者深入学习。 ... [详细]
  • 本文介绍了在Python张量流中使用make_merged_spec()方法合并设备规格对象的方法和语法,以及参数和返回值的说明,并提供了一个示例代码。 ... [详细]
  • MySQL多表数据库操作方法及子查询详解
    本文详细介绍了MySQL数据库的多表操作方法,包括增删改和单表查询,同时还解释了子查询的概念和用法。文章通过示例和步骤说明了如何进行数据的插入、删除和更新操作,以及如何执行单表查询和使用聚合函数进行统计。对于需要对MySQL数据库进行操作的读者来说,本文是一个非常实用的参考资料。 ... [详细]
  • 本文介绍了如何使用MATLAB调用摄像头进行人脸检测和识别。首先需要安装扩展工具,并下载安装OS Generic Video Interface。然后使用MATLAB的机器视觉工具箱中的VJ算法进行人脸检测,可以直接调用CascadeObjectDetector函数进行检测。同时还介绍了如何调用摄像头进行人脸识别,并对每一帧图像进行识别。最后,给出了一些相关的参考资料和实例。 ... [详细]
  • 从批量eml文件中提取附件的Python代码实现方法
    本文介绍了使用Python代码从批量eml文件中提取附件的实现方法,包括获取eml附件信息、递归文件夹下所有文件、创建目的文件夹等步骤。通过该方法可以方便地提取eml文件中的附件,并保存到指定的文件夹中。 ... [详细]
  • Problemexplanation: ... [详细]
author-avatar
etqq
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有