【问题标题】:Boost Graph Library - Minimum Spanning Tree of a Directed GraphBoost Graph Library - 有向图的最小生成树
【发布时间】:2016-10-16 14:55:11
【问题描述】:

我有一个问题需要我在 Boost Graph Library 中找到有向图的最小生成树。

我的第一次尝试是使用深度优先搜索和 DFS-visitor。我的计划是忽略除树边缘回调之外的所有边缘。这不起作用,我在下面给出一个例子说明原因。

我的问题是我是否可以让我的 dfs-visitor 在 BGL 中创建一个有向图的最小生成树。

它有一些算法,并已在此处讨论 (Finding a minimum spanning tree on a directed graph),但我无法确定它是否已针对 BGL 实现,或者它只是对 BGL 中已有内容的简单修改。

#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/depth_first_search.hpp>


struct my_visitor : public boost::dfs_visitor<>
{
    template <class Edge, class Graph>
    void back_edge(Edge e, const Graph&) 
    {
        std::cout << "Back edge: " << e << std::endl;
    }

    template <class Edge, class Graph>
    void forward_or_cross_edge(Edge u, const Graph& g)
    {
        std::cout << "Forward or cross edge: " << u << std::endl;
    }

    template <class Edge, class Graph>
    void tree_edge(Edge u, const Graph& g)
    {
        std::cout << "Tree Edge: " << u << std::endl;
    }
};


int main()
{
    using namespace boost;

    typedef boost::adjacency_list< listS, vecS, bidirectionalS > digraph;

    // Construct the directed graph
    digraph g(2);

    add_edge(1, 0, g);
    //add_edge(0, 1, g);

    my_visitor vis2;
    boost::depth_first_search(g, visitor(vis2));

    return 0;
}

这是失败的示例。如果我有以下有向图

digraph G {
0;
1;
1->0 ;
}

深度优先搜索dfs-visitor,1->0归类为前向边。

如果图形被改变,边是 0->1,那么它就是树边。

从前边的严格定义和DFS的源码来看,由于顶点0在顶点1之前被访问,所以是前边。

但是,从技术意义上讲,边缘 1->0 仍然是树边缘,并且根据他们页面中给出的定义为 http://www.boost.org/doc/libs/1_59_0/libs/graph/doc/graph_theory_review.html

前向边是连接顶点 u 到 a 的非树边 (u,v) 搜索树中的后代 v。

那么,BGL 中是否有一个简单的解决方案,还是我必须为此在 BGL 中实现其中一种算法?

【问题讨论】:

    标签: algorithm boost graph tree boost-graph


    【解决方案1】:

    我最终使用了 here 的 Edmonds 算法。感谢 HueHang,但在收到您的回复之前,我最终找到了算法并使用了它。这个问题在大约 3 周内仍未得到解答。

    这是我使用 edmonds_optimum_branching.hpp 的简单测试程序。

    #include <iostream>
    #include <vector>
    #include <utility>
    #include <iterator>
    #include <cerrno>
    #include <boost/concept_check.hpp>
    #include <boost/operators.hpp>
    #include <boost/multi_array.hpp>
    #include <boost/graph/topological_sort.hpp>
    #include <boost/graph/adjacency_list.hpp>
    #include <boost/graph/graph_traits.hpp>
    #include <boost/graph/graph_concepts.hpp>
    
    #include "edmonds_optimum_branching.hpp"
    
    typedef boost::property<boost::edge_weight_t, double>       EdgeProperty;
    typedef boost::adjacency_list<boost::listS,
                                  boost::vecS,
                                  boost::directedS,
                                  boost::no_property,
                                  EdgeProperty>                 Graph;
    typedef boost::graph_traits<Graph>::vertex_descriptor       Vertex;
    typedef boost::graph_traits<Graph>::edge_descriptor         Edge;
    
    void main()
    {
        const int N = 3;
        Graph G(N);
    
        std::vector<Vertex> the_vertices;
        BOOST_FOREACH (Vertex v, vertices(G))
            the_vertices.push_back(v);
    
        add_edge(the_vertices[0], the_vertices[2], 1.0, G);
        add_edge(the_vertices[2], the_vertices[1], 1.0, G);
        add_edge(the_vertices[1], the_vertices[0], 1.0, G);
    
        std::vector<Edge> branching;
        edmonds_optimum_branching<true, false, false>(G,
            get(boost::vertex_index_t(), G),
            get(boost::edge_weight_t(), G),
            static_cast<Vertex *>(0),
            static_cast<Vertex *>(0),
            std::back_inserter(branching));
    
        for each (Edge e in branching)
            std::cout << "(" << boost::source(e, G) << ", " << boost::target(e, G) << ")\t" << std::endl;
    }
    

    运行示例代码时,我得到的正确答案为 (2, 1) 和 (0, 2)。

    算法返回最佳分支的边缘。它还具有加权边缘,并且可以找到最小或最大权重树。我只使用上面示例中的权重 1,因为我不需要加权图。它还可以为乔木采摘根。

    【讨论】:

      【解决方案2】:

      正如您可能已经知道的那样,您正在处理的问题是在我们处理有向图时搜索最小权重的跨越树状结构。树状图是具有指定根顶点r 的图,这样所有其他顶点都可以从r 到达,即存在从r 到图中所有其他顶点的路径。

      不幸的是,Boost Graph Library 中没有解决此问题的算法,因此您需要使用像 one 这样的第 3 方实现或自己实现一个。上面给出的实现(通过 github.com 上的 atofigh)使用 Edmond's algorithm,这是解决跨越树状问题的流行算法。

      请记住,Kruskal 算法或 Prim 算法等算法不适用于有向图,因为 cut 属性不适用于有向图。

      【讨论】:

        猜你喜欢
        • 2011-02-17
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-04-18
        • 1970-01-01
        相关资源
        最近更新 更多