我需要检查是否有向图强烈连接 ,或者,换句话说,如果所有的节点可以由任何其他节点到达(不一定通过直接边缘)。
这样做的一种方式运行的每一个节点上的DFS和BFS和看到所有其他国家仍然可达。
有没有更好的方法来做到这一点?
我需要检查是否有向图强烈连接 ,或者,换句话说,如果所有的节点可以由任何其他节点到达(不一定通过直接边缘)。
这样做的一种方式运行的每一个节点上的DFS和BFS和看到所有其他国家仍然可达。
有没有更好的方法来做到这一点?
的Tarjan的强连通分量算法(或Gabow的过程的变化)就足够了; 如果只有一个强连通分量,则该图形是强烈地连接。
两者都是线性时间。
与通常的深度优先搜索,你跟踪每个节点的状态:新的,看到的却依然开放(它在调用堆栈),并看到和完成。 此外,您存储深度,当你第一次到达一个节点,而最低的这样的深度是从节点到达(你知道这你完成一个节点之后)。 节点是一个强连接组件的根如果最低可达深度等于其自身的深度。 这个工程即使通过其到达从根节点的深度是不是最小的可能。
要检查只是整个图形无论是单SCC,启动从任何一个节点的DFS,当你完成,如果最低可达深度为0,并参观了每一个节点,那么整个图是强连通的。
考虑下面的算法。
开始在随机顶点v
的曲线图的G
,并运行DFS(G, v)
如果DFS(G, v)
未达到图中的每个其它顶点G
,则存在一些顶点u
,使得没有来自向路径v
到u
,因此G
不是强连接 。
如果是这样达到的每个顶点,那么有从引导路径v
到图中的每个其它顶点G
。
扭转在所述有向图的所有边的方向G
。
再次运行DFS
开始v
。
如果DFS无法到达的每个顶点,再有就是一些顶点u
,从使得原始图有没有向路u
到v
。
在另一方面,如果它确实达到每个顶点,然后在原来的曲线有一个从每个顶点的有向路径u
到v
。
因此,如果G“通过”既DFSS,强烈连接。 此外,由于运行DFS在O(n + m)
时,该算法在运行O(2(n + m)) = O(n + m)
的时间,因为它需要2个DFS遍历。
要检查是否每一个节点具有到和从在一个给定的图形每一个其他节点的两条路径:
的Tarjan的算法假设每个节点具有一深度d[i]
最初,根具有最小深度。 而我们做的后序DFS更新d[i] = min(d[j])
对于任何邻居j
的i
。 实际上BFS也能正常工作与减速规则d[i] = min(d[j])
在这里。
function dfs(i)
d[i] = i
mark i as visited
for each neighbor j of i:
if j is not visited then dfs(j)
d[i] = min(d[i], d[j])
如果存在从一个转发路径u
到v
,然后d[u] <= d[v]
在SCC, d[v] <= d[u] <= d[v]
因此,在SCC所有节点将具有相同的深度。 判断一个图是一个SCC,我们检查所有节点是否有相同的d[i]
这是一个简化版本kosaraju算法 。 从根开始,我们检查,如果每个节点可以通过DFS / BFS到达。 然后,反向每边缘的方向。 我们检查,如果每个节点可以是同根再次达到。 见C ++代码 。
你可以计算出所有点对最短路径 ,看看有没有是无限的。
的Tarjan的算法已经被提及。 但我经常发现kosaraju算法更容易,即使它需要的图形两次遍历跟随。 IIRC,它也很好的解释CLRS。
test-connected(G)
{
choose a vertex x
make a list L of vertices reachable from x,
and another list K of vertices to be explored.
initially, L = K = x.
while K is nonempty
find and remove some vertex y in K
for each edge (y, z)
if (z is not in L)
add z to both L and K
if L has fewer than n items
return disconnected
else return connected
}
这样做的一个方法是生成拉普拉斯矩阵的图形,然后计算特征值,最后算上零的个数。 该图是强连接,如果只存在一个零特征。
注意:对于有向图创建拉普拉斯矩阵注意略有不同的方法。
您可以使用基于Kosaraju的DFS简单的算法,做图的两条DFS遍历:
我们的想法是,如果每个节点可以从一个顶点v到达,每一个节点都可以达到V,则该图是强连通。 在算法的步骤2中,我们检查是否所有的顶点是从V可到达的。在步骤4中,我们检查是否所有的顶点可以达到V(在相反的曲线图中,如果所有的顶点是从V可达,则所有的顶点可以达到在原v图形)。
算法:1)初始化所有的顶点为没有去过。
2)你从任意顶点v开始图表的DFS遍历。如果DFS遍历没有访问所有顶点,然后返回false。
3)反向所有弧(或发现移调或图形的反向)
4)标记所有顶点不-走访反转图形。
5)执行反转图形的DFS遍历从同一顶点v(同步骤2)开始。 如果DFS遍历没有访问所有顶点,然后返回false。 否则返回true。
时间复杂性:时间以上实现的复杂度是相同深度优先搜索,其为O(V + E)如果该图是使用邻接列表表示来表示。