Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 确定有向图是否为单连通的最有效方法是什么?_Algorithm_Adjacency List_Directed Graph - Fatal编程技术网

Algorithm 确定有向图是否为单连通的最有效方法是什么?

Algorithm 确定有向图是否为单连通的最有效方法是什么?,algorithm,adjacency-list,directed-graph,Algorithm,Adjacency List,Directed Graph,我正在处理一个赋值问题,其中一个问题要求导出一个算法来检查有向图G=(V,E)是否是单连通的(对于V的所有不同顶点u,V,V,最多有一条从u到V的简单路径) 当然你可以用暴力检查,这就是我现在正在做的,但我想知道是否有更有效的方法。有人能给我指出正确的方向吗?你试过了吗 复杂性O(v^2),O(v)dfs是不重复的。这个问题有一个更好的答案。你可以在O(|v | ^2)中完成。你可以在线性时间内完成 首先找到G的强连通分量。在每个强分量中,搜索以找到以下情况: 1) 如果此组件中有前缘,则它不是

我正在处理一个赋值问题,其中一个问题要求导出一个算法来检查有向图G=(V,E)是否是单连通的(对于V的所有不同顶点u,V,V,最多有一条从u到V的简单路径)

当然你可以用暴力检查,这就是我现在正在做的,但我想知道是否有更有效的方法。有人能给我指出正确的方向吗?

你试过了吗


复杂性O(v^2),O(v)dfs是不重复的。

这个问题有一个更好的答案。你可以在O(|v | ^2)中完成。你可以在线性时间内完成

首先找到G的强连通分量。在每个强分量中,搜索以找到以下情况: 1) 如果此组件中有前缘,则它不是单独连接的, 2) 如果此组件中存在交叉边,则它不是单独连接的, 3) 若树中至少有两条后边以顶点u为根,指向u的适当祖先,那个么它不是单连通的

这可以在O(E)中完成。(我认为除了案例3,我不能很好地实施它!!)


如果上述情况均未发生,则应检查G^SCC(图G,强组件替换为单个节点)上是否存在交叉边或前向边,因为我们没有后缘,可以通过在O(| V | ^2)中重复此图的每个顶点上的dfs来完成此操作。

从每个顶点运行一次dfs。图是单连通的if和 仅当一个区域内没有前向边和交叉边时 组成部分


复杂度:O(V.E)

我不同意它的复杂度是O(V^2),因为在DFS中,我们并不是对每个顶点都调用它,正如《算法简介》一书中所述,语法是DFS(G)。与BFS不同,我们只对整个图调用DFS,而不对任何单个顶点调用DFS。因此,在这种情况下,根据我的说法,我们必须通过调用DFS一次来检查它。如果再次遇到访问的顶点,则该图不是单独连接的(我们必须为每个断开连接的组件调用它,但它已经包含在代码中)。因此,复杂性将是O(V+E)。因为这里E=V,所以复杂性应该是O(V)。

我想到了这一点: 1) 从任何顶点运行DFS,如果DFS中的所有顶点都被覆盖,且没有前向边(不能有交叉,否则不会覆盖所有顶点),则它可能是一个潜在的候选顶点

2) 如果在DFS中找到的某个顶点(级别j)有一个到级别i的后缘,则在其后找不到任何其他顶点,该顶点的后缘应朝向级别小于j的任何顶点,并且每个顶点都可以到达根(使用第二个DFS检查)


如果这是正确的,它在线性时间内完成

阅读。这确实解释得很好。

看看简单路径的定义。循环图可以是单连通的<代码>DFS不适用于单独连接的
A->B,B->A

下面的文章使用强连通组件来解决这个问题


我在别处读到,在整个树上运行一次DFS就足够了。是否有必要在每个顶点上运行?对每个未访问的顶点重复此操作就足够了,但您必须在下游重新遍历所有对象(即使是标记为“未访问”的对象)。因此,您需要“曾经访问过”和“这次访问过”标记。运行DFS一次是否就足够了,在运行DFS之后,我们检查是否没有交叉边和前向边,然后我们就完成了?是否存在这样一种情况,即运行一个DFS并检查交叉边和前向边是不够的,因为任意两个节点u和v之间的任何多条路径都将显示在我们的DFS中?如果交叉边位于DFS林中的树之间,则交叉边不违反单连通图。交叉边可能位于从u到v的唯一路径上。在这种情况下,运行DFS一次是否足够,并检查是否存在任何前向边或树内交叉边?那将是O(V+E)…如果交叉边是从另一棵树的根到另一棵树的子树的话会怎样。这是一个完全合法的边缘。为什么后端相关?他们不是从来没有走过一条简单的路吗?@pkoch,他已经说过,在3)中,如果树的两个后缘都扎根于顶点u,指向u的正祖,那么它就不是单独相连的,因为有一个后边的有向环仍然是一个单连通图。第三点可以简单地用一个数组来计算某个顶点的后边数。每当后缘指向SCC中的适当祖先时,我们将arr[v]增加1。当它达到>=2时,我们将其打破。这个问题非常类似于按顶点的时间线性顺序寻找唯一路径图。必须使用SCC来解决此类问题。使用SCCs和SCC图可以简化许多检查。对于那些无法打开postscript链接的人,引用:单连通性的O(| V | ^2)算法,Samir Khuller。
Run DFS for every vertex in the graph as source
    If a visited vertex is encountered again, the graph is not singly connected
repeat for every unvisited vertex.
The graph is singly connected.