无向图—桥

无向图—桥

实验概述

1. 桥的定义

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

找出一个无向图中所有的桥。

3. 算法

基准算法

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.

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

实验思路

并查集-LCA找环

首先先来回顾一下并查集(一般在讲kruskal的时候会讲):三个操作Make-set、Find-set和Union。

Union操作发现环边

Union时,如果两个点已经在同一个集合内了,那么这条边一定是环边。并且一旦加入了这条边,就会形成环。这意味着它是使环闭合的边。

那么可以从环边的点1出发,找一条路到达环边的另一个点2,将所有经过的边标记为环边。事实上,就是找一条从点1到点2的路径。在生成树中,就意味着两个点至少有一个公共祖先。
无向图—桥_第2张图片
证明:顺序不同也可以找到环

已知union发现的环边一定是添加了该边就刚好构成环的边。那么如果这条边在多个环上,既点1到点2有多条路径,那么这些路径本身就构成环,在之前就已经标记了环边。所以无论走了哪条路,最后都能完全找到所有环边。
无向图—桥_第3张图片
生成树找环

沿着生成树找公共祖先,既LCA。同时沿途经过的边也是环边。如图,1-4加入后,从4往上找1,经过的边也都是环边。
无向图—桥_第4张图片
无向图—桥_第5张图片
无向图—桥_第6张图片
路径压缩

为了加快向上找祖先的速度,可以用路径压缩。如图,要从6到2需要向上走很多步,但有6-5-1-2这条更短的路径。能否用上5-1这条路呢?每个点都有一个father结点,在此处我们将father指向公共祖先。所以6到5之后会直接跳向1,此时2比1深,2向上找到1。

5->1的过程中,会将经过的点的father都设为公共祖先1。6->2过程中,最后也会将6的head设为1。
无向图—桥_第7张图片
并查集建生成树

在建立并查集时同时建立一颗生成树。此时一个结点就有一个father、一个level和一个head。在union时,要查看这条边的两个结点是否在树中。如果

  1. 一个在一个不在,不在的那个的father设为在的那个;

  2. 两个都不在,随机;
    无向图—桥_第8张图片

  3. 两个都在,这是条环边:

​ 1) 两个点在同一颗树中,从level小的开始向前寻找。

​ 2)两个点在不同树中,合并树。(这条边暂时不是环边)

​ 向上寻找时,每经过一个结点,我们会把father改为head。

合并树的方法:

  1. 选择一棵树T;

  2. 修改T中从要合并的点开始,向上反转的father;

  3. 合并并查集,修改T中每个点的head和并查集的tail。
    无向图—桥_第9张图片
    合并并查集(修改head)时,每个结点向上寻找到已经更新的祖先,更新level。

优化:将小的树并入大的树。这一步非常关键,实测可以提升至少50倍速度。

你可能感兴趣的:(算法)