设计一个复杂度为 O(V+E) 的算法,用于确定从边列表 S 中按顺序删除边时图在什么点断开
Design a O(V+E) algorithm for determining at what point a graph becomes disconnected when deleting edges sequentially from a list of edges S
给定一个连通图 G 和一系列边 S。从 G 中删除 S 的一条边。然后检查 G 是否仍然连通。如果 G 不再连接,则您 return 边缘。否则,您从图中删除边并继续。
我最初的想法是使用 Tarjan 的桥查找算法,该算法构建 DFS 树,然后检查给定的顶点是否具有将其后代之一与其祖先之一连接的后边。如果没有,那就是一座桥。
您可以在构建树时在 O(V+E) 时间内找到所有的桥,但我在调整 Tarjan 的算法以解决删除问题时遇到了问题。每次删除边时,树都会发生变化,我无法将算法保持在 O(V+E) 时间。有什么想法吗?
Find the bridge edges
FOR E in S
IF E is a bridge
STOP
remove E
IF E1 is disconnected ( zero edges on E1 )
STOP
IF E2 is disconnected
STOP
E1和E2是由E连接的顶点
您可以在 almost-linear、O(E * alpha(V))
时间内相当轻松地完成此操作,其中 alpha 是 ridiculously-slowly-growing inverse-Ackermann 函数,使用 disjoint-set data structure。 诀窍是反转 S
并添加边 ,因此您询问 G
何时首次连接,而不是断开连接。增量连接问题比递减连接问题要容易得多。
给定 disjoint-set 的实现,您可以扩充它以跟踪组件的数量,并且当只有一个组件时,图是准确连接的。如果您从 n
个组件开始,那么在任何 Union(x, y)
操作之前,请检查 x
和 y
是否属于同一组件。如果他们不这样做,则并集操作会将图形的组件减少 1。
对于您的图表,您需要预处理 S
以找到 G
中不在 S
中的所有边,并将它们添加到 disjoint-set 首先是数据结构。然后,如果添加 S[i]
导致图形第一次连接,答案是 i
,因为我们已经添加了 S[i+1], S[i+2], ... S[n-1]
.
最佳复杂度
对于适合我们宇宙的任何输入,inverse-Ackermann 函数最多 4
,因此我们的 Union-find 算法通常被认为是 'pretty much linear'。但是,如果这还不够好...
您可以在 O(V+E)
中执行此操作,尽管它相当复杂,而且可能主要是理论上的兴趣。 Gabow and Tarjan's 1984 paper 发现一种算法支持 Union-Find O(1)
如果我们知道所有联合操作的顺序,则每次操作的摊销成本,我们在这里这样做。它仍然使用disjoint-set数据结构,但增加了额外的辅助结构来缓存小集上的节点信息。
文中提供了一些伪代码,但您可能需要自己实现或在线查找实现。它也只适用于 word RAM model,因为它从根本上依赖于在恒定时间内操纵小的 bit-strings 以将它们用作查找表(一个相当标准的假设,但你需要做一些 low-level位操作)。
给定一个连通图 G 和一系列边 S。从 G 中删除 S 的一条边。然后检查 G 是否仍然连通。如果 G 不再连接,则您 return 边缘。否则,您从图中删除边并继续。
我最初的想法是使用 Tarjan 的桥查找算法,该算法构建 DFS 树,然后检查给定的顶点是否具有将其后代之一与其祖先之一连接的后边。如果没有,那就是一座桥。
您可以在构建树时在 O(V+E) 时间内找到所有的桥,但我在调整 Tarjan 的算法以解决删除问题时遇到了问题。每次删除边时,树都会发生变化,我无法将算法保持在 O(V+E) 时间。有什么想法吗?
Find the bridge edges
FOR E in S
IF E is a bridge
STOP
remove E
IF E1 is disconnected ( zero edges on E1 )
STOP
IF E2 is disconnected
STOP
E1和E2是由E连接的顶点
您可以在 almost-linear、O(E * alpha(V))
时间内相当轻松地完成此操作,其中 alpha 是 ridiculously-slowly-growing inverse-Ackermann 函数,使用 disjoint-set data structure。 诀窍是反转 S
并添加边 ,因此您询问 G
何时首次连接,而不是断开连接。增量连接问题比递减连接问题要容易得多。
给定 disjoint-set 的实现,您可以扩充它以跟踪组件的数量,并且当只有一个组件时,图是准确连接的。如果您从 n
个组件开始,那么在任何 Union(x, y)
操作之前,请检查 x
和 y
是否属于同一组件。如果他们不这样做,则并集操作会将图形的组件减少 1。
对于您的图表,您需要预处理 S
以找到 G
中不在 S
中的所有边,并将它们添加到 disjoint-set 首先是数据结构。然后,如果添加 S[i]
导致图形第一次连接,答案是 i
,因为我们已经添加了 S[i+1], S[i+2], ... S[n-1]
.
最佳复杂度
对于适合我们宇宙的任何输入,inverse-Ackermann 函数最多 4
,因此我们的 Union-find 算法通常被认为是 'pretty much linear'。但是,如果这还不够好...
您可以在 O(V+E)
中执行此操作,尽管它相当复杂,而且可能主要是理论上的兴趣。 Gabow and Tarjan's 1984 paper 发现一种算法支持 Union-Find O(1)
如果我们知道所有联合操作的顺序,则每次操作的摊销成本,我们在这里这样做。它仍然使用disjoint-set数据结构,但增加了额外的辅助结构来缓存小集上的节点信息。
文中提供了一些伪代码,但您可能需要自己实现或在线查找实现。它也只适用于 word RAM model,因为它从根本上依赖于在恒定时间内操纵小的 bit-strings 以将它们用作查找表(一个相当标准的假设,但你需要做一些 low-level位操作)。