|
|
Строка 43: |
Строка 43: |
| | | |
| === Псевдокод === | | === Псевдокод === |
− | '''dfs'''(<tex>v, p</tex>) | + | '''dfs'''(<tex> v </tex>) |
| <tex> time \leftarrow time + 1</tex> | | <tex> time \leftarrow time + 1</tex> |
| <tex>enter[v] \leftarrow time</tex> | | <tex>enter[v] \leftarrow time</tex> |
| <tex>ret[v] \leftarrow time </tex> | | <tex>ret[v] \leftarrow time </tex> |
| '''for''' всех <tex>u</tex> смежных с <tex>v</tex> | | '''for''' всех <tex>u</tex> смежных с <tex>v</tex> |
− | ''if'' <tex>u = p</tex> '''continue''' | + | ''if'' <tex>(v, u)</tex> - обратное ребро |
| + | <tex>ret[v] \leftarrow min(ret[v], enter[u])</tex> |
| + | '''if''' вершина <tex>u</tex> - белая |
| + | '''dfs'''(u) |
| + | <tex> ret[v] \leftarrow min(ret[v], ret[u]) </tex> |
| + | '''if''' <tex>ret[u] > enter[v]</tex> |
| + | ребро <tex>(v, u)</tex> - мост |
Версия 11:09, 8 декабря 2010
Постановка задачи
Дан неориентированный граф [math] G [/math]. Найти все мосты в [math] G [/math] за время [math] O(|V| + |E|)[/math]
Алгоритм
Теория
Теорема: |
Пусть [math] T [/math] - дерево обхода в глубину графа [math] G[/math]. Ребро [math] (u, v) [/math] является мостом тогда и только тогда, когда [math] (u, v) \in T[/math] и из вершины [math] v[/math] и любого ее потомка нет обратного ребра в вершину [math] u[/math] или предка [math] u [/math] |
Доказательство: |
[math]\triangleright[/math] |
[math] \Leftarrow[/math]
Удалим [math] (u, v)[/math] из [math] G[/math] Докажем, что мы не сможем достичь ни одного из предков [math] v [/math] (в частности [math] u [/math]). Пусть это не так, и [math] w[/math] - предпоследняя вершина на пути от [math] v[/math] до ее предка [math]x [/math]. Очевидно, [math] (w, x)[/math] не ребро дерева (в силу единственности пути в дереве). Если [math] (w, x)[/math] - обратное ребро, то это противоречит условию теоремы, т.к. [math] x[/math] - предок [math] u[/math]
[math] \Rightarrow[/math]
Докажем что из отрицания второго утверждения следует отрицание первого.
Пусть существует удовлетворяющее условию обратное ребро [math](x, w)[/math]. Тогда [math](u, v)[/math] лежит на цикле [math]x \rightsquigarrow v \rightarrow u \rightsquigarrow w \rightarrow x[/math] и не может быть мостом. |
[math]\triangleleft[/math] |
Функция [math]ret(v)[/math]
Определим функцию [math]ret(v)[/math], где [math]v \in V[/math], как минимум из следущих величин
[math]enter(v)[/math]
[math]enter(x)[/math], где [math]x[/math] - потомок [math]v[/math]
[math]enter(x)[/math], где [math](w, x)[/math] - обратное ребро, а [math]w[/math] - потомок [math]v[/math] (в нестрогом смысле)
Лемма: |
Ребро [math](u, v)[/math] является ребром тогда и только тогда, когда [math](u, v)[/math] принадлежит дереву обхода в глубину и [math]ret(v) \gt enter(u)[/math] |
Доказательство: |
[math]\triangleright[/math] |
Так как на пути от вершины к корню дерева величины [math]enter[/math] убывают, то [math]ret(v)[/math] возвращает величину [math]enter[/math] для ближайшей к корню вершины, достижимой из [math]v[/math] или ее потомка, возможно используя одно обратное ребро. Следовательно, из вершины [math]v[/math] или ее потомков существует обратное ребро потомка [math]u[/math] или саму [math]u[/math] тогда и только тогда, когда [math]ret(v) \lt = enter(u)[/math]. По доказанной теореме, отсутствие такого ребра эквивалентно тому что [math](u, v)[/math] - мост. |
[math]\triangleleft[/math] |
Лемма: |
[math]ret(v)[/math] = минимум из
[math]enter(v) [/math]
[math]enter(p)[/math], [math](v, p)[/math] - обратное ребро
[math]ret(u)[/math], [math](v, u)[/math] - ребро дерева |
Доказательство: |
[math]\triangleright[/math] |
1)[math]enter(v) [/math]
По определению функции [math]ret[/math]
2)[math]enter(p)[/math], [math](v, p)[/math] - обратное ребро
[math]p[/math] достижима из [math]v[/math] по одному обратному ребру, значит величина [math]ret(v)[/math] не больше [math]enter(p)[/math]
3)[math]ret(u)[/math], [math]u[/math] - потомок [math]v[/math]
Так как вершина [math]u[/math] - потомок [math]v[/math], то обратное ребро из ее поддерева является обратным ребром из поддерева [math]v[/math] |
[math]\triangleleft[/math] |
Псевдокод
dfs([math] v [/math])
[math] time \leftarrow time + 1[/math]
[math]enter[v] \leftarrow time[/math]
[math]ret[v] \leftarrow time [/math]
for всех [math]u[/math] смежных с [math]v[/math]
if [math](v, u)[/math] - обратное ребро
[math]ret[v] \leftarrow min(ret[v], enter[u])[/math]
if вершина [math]u[/math] - белая
dfs(u)
[math] ret[v] \leftarrow min(ret[v], ret[u]) [/math]
if [math]ret[u] \gt enter[v][/math]
ребро [math](v, u)[/math] - мост