我需要在O(V + E)时间内确定无向图中的所有关键边。根据我的发现,我需要使用修改后的DF搜索,但我找到的所有伪代码算法都有低[v]和d [v],我不明白。有人可以向我解释O(V + E)桥梁确定算法吗?
答案 0 :(得分:9)
我将故意非正式地讨论。如果您认为某些声明不成立或需要更多细节,请随时询问。 我希望我不会太过于喋喋不休。如果我这样做,我会在某种程度上浓缩这部小说......
该算法由一系列dfs遍历组成,同时保持图形顶点的状态。重复地,选择之前未访问算法的起始顶点,并从该节点开始dfs。让v
成为在此dfs期间被占用的节点。让以v
'为根的'部分dfs'成为dfs遍历的一部分,从第一次访问开始到最后一次访问v
结束。对某个节点的“访问”要求最后一个遍历的边缘是树边缘。对某些边缘的“访问”意味着它在dfs过程中的第一次遍历。
2基本观察:
1。
将会有k
次dfs搜索,其中k
是已连接组件的数量。
2。 在无向图上的dfs中,只有树和后边,但没有前沿或交叉边。
在无向图中,入射到顶点的所有边都是“向外”边,即。可以在dfs中遍历。因此,在连接组件#i中的dfs搜索中的任何时候,遇到的任何顶点都从未被访问过或者位于当前的dfs树路径上。因此,dfs到达所述顶点的边缘是树边缘或后边缘,但不能是前沿或交叉边缘。
算法在顶点上保留以下信息。 首先,让顶点状态为3类之一:
unseen
:尚未访问该顶点。active
:已经访问了顶点,至少有一个但不是全部的事件边缘。done
:已访问顶点及其所有事件边缘。永远不会再访问顶点。定义意味着每个顶点将其状态从unseen
更改为active
到算法的done in the
过程。
在顶点上维护处理状态的另外两个方面:
depth
:顶点与当前dfs根目录的树路径距离。minseen
:在以顶点为根的部分dfs期间遇到的最小顶点“深度”。 depth
和minseen
将是未定义的。
当转动active
时,顶点的depth
将被设置并且永远不会再次改变。 minseen
将设置为depth
,并且在此顶点保持active
时可能会发生变化。进入状态done
后,顶点看不到其minseen
属性的更改。
minseen
根据以下规则进行更新:
从w
回溯到v
时(即,在w
中的部分dfs搜索完成后,从节点v
返回到w
, v.minseen
设置为v.minseen
和w.minseen
的较小值,即。到目前为止在v
部分dfs期间访问的任何节点之间的最近距离。
如果e=(u,v)
是当前dfs中的桥,则v
处的部分dfs在任何时候都不会到达比u
更接近dfs根的顶点。因此,在状态从v
更改为active
后立即离开done
时,节点的minseen
属性将等于depth
。由于状态的变化,我们知道这两个值都不会再发生变化。因此e
是一座桥梁。
切换透视图,如果在以v
为根的部分dfs期间的任何时间,在当前dfs的根目录和{{之间的树路径上遇到active
节点z
1}}(其u
值因此小于depth
和u
'),v
将在z.depth
期间渗透回v
dfs定义了v.minseen
的最终值的上限 - 所以当dfs离开v.depth
时最后一次显示v
不是桥梁时,它不能等于e
以预定顺序检查所有顶点一次。当遇到unseen
顶点时,dfs开始以此顶点为根。结束时,此根标记为done
,检查将继续,直到找到下一个unseen
顶点,依此类推。
- > O(V)
由于遍历是标准dfs,每条边最多遍历两次(如果是树边,则两次,否则一次)。
- > O(E)
- > O(V+E)
所有其他步骤转化为恒定数量的操作。