用于测试G是否包含树枝的算法

时间:2014-01-06 17:31:33

标签: graph

有向图G的树状结构是有根树,因此在图中存在从根到每个其他顶点的有向路径。提供一种有效且正确的算法来测试G是否包含一个树状及其时间复杂度。

我只能考虑从每个节点运行DFS / BFS,直到其中一个DFS覆盖了所有节点。 我想过使用最小生成树算法,但这也仅适用于非定向图

还有其他有效的算法吗?

我发现了一个跟进问题,其中说明有一个O(n + m)算法,任何人都可以帮助解决这个问题吗?

3 个答案:

答案 0 :(得分:6)

您正在寻找的是所谓的Edmond算法。最小生成树算法不适用于有向图,但这是一个想法。当图表被指示并且树状结构是您在上面描述的时候,MST问题变成了树状问题。

天真的复杂性是O(EV),就像Prim的无向MST问题算法一样,但我确信它的实现速度更快。

有关详细信息,请查看Wiki页面:

Edmonds Algorithm

答案 1 :(得分:1)

首先要注意的是,上述问题中给出的有向图的树状结构的定义与例如在Wikipedia:您的问题的定义不要求路径是唯一的,也不要求原始有向图G是加权的。因此,解决方案应该比Edmond's Algorithm处理的解决方案更简单。

以下内容如下:第一部分将是找到一个足够的根。一旦找到足够的根,从该根开始在图G上运行一个简单的DFS应该允许我们创建所需的树,我们就完成了。那么我们怎样才能找到这样的根?

  • 首先运行DFS并“减少”发现单边的任何循环。在任何发现的循环中,无论我们使用哪个边缘,因为它们中的任何一个都可以到达任何其他边缘。如果在减少之后留下单个边缘,则意味着整个图形是强连接的,因此任何边缘 - 包括唯一的边缘 - 都可以作为根。

  • 如果剩下多个边,则遍历所有剩余边,找到入度为零的边。如果找到多个 - 那么我们就无法构建所需的树 - 因为它们无法彼此联系。如果在这里只找到一条边 - 那就是我们的根边缘。

复杂性是O(边缘+顶点),比如说图的邻接列表表示。

答案 2 :(得分:0)

我认为这比我想象的要简单得多。在线程开头已经提到的类似行中的东西。因此,基本上使用BFS在图形中的任何节点上启动DFS遍历,并尽可能地达到,然后一旦完成。只需获取下一个未访问的顶点并再次进行BFS遍历,并且遇到已经处理的节点意味着这已经处理了子树,并且通过该节点可到达的所有节点将通过另一个节点到达节点,从而生成当前节点作为这个新子树的父级。

只需执行DFS遍历,其中每个边缘只能被访问一次。请执行以下操作

edgeCb()
{
    // Already processed and has no parent means this must a sub tree
    if ( g->par[ y ] == -1 && g->prc[ y ] )
        g->par[ y ] = x; // Connecting two disconnected BFS/DFS trees
    return 1;
}

graphTraverseDfs( g, i )
{
    // Parent of each vertex is being updated as and when it is visited.
}

main() {
.
.
for ( i = 0; i < g->nv; i++ )
    if ( !g->vis[ i ] )
        graphTraverseDfs( g, i );
.
.
}