深圳大学算法设计与分析_实验五

该实验主要探讨了图的连通性,特别是桥的概念,即删除后会导致图连通块增多的边。实验通过基准算法配合并查集、DFS等方法来寻找无向图中的桥。优化算法包括并查集优化,通过记录顶点的根节点来计算连通子图数量,以及结合DFS消除环以减少遍历的边数。此外,还讨论了生成树在找桥中的应用和DFS除环的独立使用。
摘要由CSDN通过智能技术生成


实验目的

(1) 掌握图的连通性。
(2) 掌握并查集的基本原理和应用。


实验内容

  1. 桥的定义
    在图论中,一条边被称为“桥”代表这条边一旦被删除,这张图的连通块数量会增加。等价地说,一条边是一座桥当且仅当这条边不在任何环上。一张图可以有零或多座桥。
    图 1 没有桥的无向连通图
    图 2 这是有16个顶点和6个桥的图
  2. 求解问题
    找出无向图中的所有桥
  3. 算法
    基准算法+高效算法

实验过程

1. 基准算法

先记录图的初始连通分量,然后对逐条边删去,再计算连通分量是否变化,若变化这说明是桥。
具体的实现思路:逐条边删去,并以其中一个顶点作为起点进行DFS,若DFS能够经过另一个顶点,说明该边不是桥,若否则为桥。

数据结构:邻接表
同实验三的选择思路,避免发生大数据时矩阵运算导致的内存不足;同时也方便我们进行DFS搜索,减少访问相连边的时间。

伪代码:
1.	#基准法  
2.	#遍历每一条边:  
3.	    #删除该边  
4.	    #以其中一个为顶点进行DFS/BFS  
5.	    #判断另一个顶点是否被访问  
6.	    #若未访问:  
7.	        #标记为桥  

2. 优化算法

数据结构:
将图以边的形式保存在列表中进行遍历

2.1 基准法+并查集

使用一个数组记录每个顶点的根节点,最后计算数组中的根节点数目即是连通子图的数量

#关键代码
1.	def connected(p,q):  
2.	    global count  
3.	    if find(p) == find(q):  
4.	        return True  
5.	    else:              
6.	        return False  
7.	  
8.	def find(p):      
9.	    global count  
10.	    while (p != id[p]):  
11.	        p = id[p]  
12.	    return p  
13.	  
14.	def union(p,q):  
15.	    global count  
16.	    idq = find(q)  
17.	    idp = find(p)  
18.	    if not connected(p,q):  
19.	        id[idp]=idq  
20.	        count -=1  

2.1 基准法+并查集优化

由于改变某棵子树的根节点时,我们初始是默认为统一修改左子树节点的根节点,但是此时可能存在两棵树大小悬殊的问题(如图1)。因此我们添加一个列表用于记录每个顶点树的大小,在需要修改根节点时,对大小进行判断,修改树规模较小的子树。
在这里插入图片描述

1.	def union(p,q):  
2.	    global count  
3.	    idq = find(q)  
4.	    idp = find(p)  
5.	    if not connected(p,q):  
6.	        if (sz[idp] < sz[idq]):  
7.	            id[idp] = idq  
8.	            sz[idq] += sz[idp]    
9.	        else:  
10.	            id[idq] = idp  
11.	            sz[idp] += sz[idq]   
12.	        count -=1  

2.3 基准法+并查集+DFS除环

由于能构成环的边一定不可能是桥,因此我们可以使用dfs找出图中所有的基础环,将这些边删除,减少基准法遍历的边数。

1.	def dfs_cycle(graph,trace,start):  
2.	    # 如果start在trace中,则返回环  
3.	    if start in trace:  
4.	    index = trace.index(start)  
5.	            tmp = [str(i) for i in trace[index:]]  
6.	            ans.add( str(' '.join(tmp)))  
7.	            #print(trace[index:])  
8.	            return  
9.	    # 深度优先递归递归  
10.	    for i in graph[start]:  
11.	        dfs(graph,trace,i)  

2.4 基准法+并查集+生成树(Prim算法)

一个连通图的生成树是一个极小的连通子图,它包含图中全部的n个顶点,但只有构成一棵树的n-1条边。生成树当中不存在环;移除生成树中的任意一条边都会导致图的不连通,且在生成树中添加一条边会构成环。
因此,桥一定会在生成树上,这其实也是一种减少遍历次数的方法。但是由于这种方法会保留环的某几条边,与我们上一个去除所有构成环的边算法相比不算太优越。

3. DFS除环

DFS除环其实不需要与并查集合并,直接除掉不在环上的就是桥。但是由于我一开始DFS除桥代码编写没有除彻底,因此将其和并查集合并起来,又进行了一次探索。
但实际上是可以直接使用DFS除环查找桥。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值