图论-桥问题

问题描述

  1. 桥的定义
    在图论中,一条边被称为“桥”代表这条边一旦被删除,这张图的连通块数量会增加。等价地说,一条边是一座桥当且仅当这条边不在任何环上。一张图可以有零或多座桥。

在这里插入图片描述
2. 求解问题
找出一个无向图中所有的桥。

(1)基准算法
For every edge (u, v), do following
a) Remove (u, v) from graph
b) See if the graph remains connected (We can either use BFS or DFS)
c) Add (u, v) back to the graph.

(2)应用并查集设计一个比基准算法更高效的算法。不要使用Tarjan算法,如果使用Tarjan算法,仍然需要利用并查集设计一个比基准算法更高效的算法。

计算连通分量的基准法

先记录下完整的图有多少连通分量,然后逐条边删去并计算连通分量的个数是否变化,若删去某条边后的连通分量增加,说明这条边是桥,这个算法完全符合桥的定义。

判断是否连通的基准算法

逐条边删去并判断删去后的图中该边的两个顶点是否连通,若连通则说明这条边不是桥。

具体的算法是:遍历每条边,并对删去该边后的图以该边的一个顶点为起点做dfs,若dfs能够经过另一个顶点,说明该边不是桥,若不能经过则是桥。

生成树筛边

上述的基准算法我们还可以进行优化,因为桥一定在生成树上,否则生成树无法把两个块连接起来。因此我们可以利用这个性质,先用一次dfs或者bfs扫出整颗生成树,然后再对生成树的边进行基准算法找桥。

数据结构

使用邻接表的算法效率远高于邻接矩阵,这主要是因为邻接矩阵包含了大量的空白边数据,因此导致了在dfs时遍历次数增多。

加上跑稀疏大图的时候邻接矩阵浪费空间过多,假如有一百万个顶点,采用邻接矩阵需要1000000*1000000个int空间,计算下来相当于3725GB的内存空间,过于耗费内存,而采用邻接表就可以节省大量空间了。

因此数据结构应采用邻接表。

DFS vs BFS

用基准算法测试大图的时候我发现DFS较为缓慢,不如BFS的效率,这可能是因为BFS可以找出最短路径,而且DFS会有栈的开销,因此用BFS判断连通的时候会更快。

而且DFS会出现递归深度过大而导致堆栈内存溢出,因为VS默认的堆栈大小只有1MB,虽然说VS可以手动调整堆栈大小,但是没从根本上解决问题。

因此我们在基准法中采用BFS进行扫描更好,效率可以得到提升。

逐条边删去判断连通的并查集算法

受到基准算法的启发,很容易就可以利用并查集设计出一种类似的算法,即逐条边删去然后更新集合最后判断该边的两个点是否仍在同一集合,如果在说明仍然连通,即该边不是桥,如果不在说明是桥。

整个算法流程如下:

1、 使用make-set操作,把每个结点的父结点置为自身,相当于自己是一个集合

2、 遍历每条边,将该边删去,然后遍历图中剩余的所有边,对这些边的两个结点进行find操作,向上找到最终父结点,然后让一个最终父结点指向另外一个最终父结点实现合并,相当于union操作。

3、 遍历完剩余的所有边之后,对删去边的两个结点进行find操作,看看最终父结点是否一样,不一样说明不连通了,该边是桥。

这个方法可以进行优化,见我另外一篇博客:启发式策略

同理,这个方法也和基准法一样可以先进行生成树筛边。

高效并查集算法

贴一个链接,挺多同学都是用这个方法,要fanqiang:并查集找桥

我用的是另外一种LCA找环的方法,对所有不在生成树的边,找出边上两个结点的最近公共祖先(LCA),途经的边都在环上,最后在生成树中去掉在环上的边剩下的就是桥。

这个方法扫生成树可以用并查集,但是树的高度不好控制。我最后是用并查集扫出每个连通分量的根,然后每个根都做BFS得到生成树,再进行上述的LCA找环算法。

BFS扫树可以让找LCA的效率高不少,因为BFS树高度低,网上还有很多提高找LCA效率的方法,可以自行尝试。

效率

用进行生成树筛边后的第二种基准法跑大图300秒左右,如果太慢可能是用了DFS或者有些数据结构没选对;LCA找环跑大图20多秒。

跑出来largeG有8座桥,mediumDG有0座。

题目来自某高校算法实验五,仅供参考

  • 0
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值