【问题标题】:DFS in boost::graph with changing the graphs content更改图形内容的 boost::graph 中的 DFS
【发布时间】:2014-05-17 00:01:19
【问题描述】:

小例子:

#include <boost/graph/graph_traits.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/depth_first_search.hpp>

struct vertex
{
    int number;
};
struct edge {};

typedef boost::adjacency_list<boost::listS, boost::vecS, boost::directedS, vertex, edge> graph_t;
typedef boost::graph_traits<graph_t>::vertex_descriptor vertex_t;
typedef boost::graph_traits<graph_t>::edge_descriptor edge_t;

struct vertex_visitor : public boost::default_dfs_visitor
{
    void discover_vertex(vertex_t v, graph_t& g)
    {
        g[v].number = 42;
    }
};

int main()
{
    graph_t g;
    vertex_t v1 = boost::add_vertex(g);
    vertex_t v2 = boost::add_vertex(g);
    boost::add_edge(v1, v2, g);

    vertex_visitor vis;
    boost::depth_first_search(g, boost::visitor(vis));

    return 0;
}

它不起作用,因为图表需要在vertex_visitor::discover_vertex() 中引用为const

有没有比编写自己的 DFS 算法(或使用const_cast)更好的方法来做我想做的事?另外,您的解决方案是否允许在发现顶点时添加/删除边和顶点?

【问题讨论】:

    标签: c++ boost graph boost-graph


    【解决方案1】:

    看看 Boost 如何实现connected_components。为了存储组件 ID,使用了以下访问者:

    // This visitor is used both in the connected_components algorithm
    // and in the kosaraju strong components algorithm during the
    // second DFS traversal.
    template <class ComponentsMap>
    class components_recorder : public dfs_visitor<>
    {
      typedef typename property_traits<ComponentsMap>::value_type comp_type;
    public:
      components_recorder(ComponentsMap c, 
                          comp_type& c_count)
        : m_component(c), m_count(c_count) {}
    
      template <class Vertex, class Graph>
      void start_vertex(Vertex, Graph&) {
        if (m_count == (std::numeric_limits<comp_type>::max)())
          m_count = 0; // start counting components at zero
        else
          ++m_count;
      }
      template <class Vertex, class Graph>
      void discover_vertex(Vertex u, Graph&) {
        put(m_component, u, m_count);
      }
    protected:
      ComponentsMap m_component;
      comp_type& m_count;
    };
    

    这个想法是将一个属性映射传递给访问者的构造函数,然后用于更新数据。关于您的示例,vertex_visitor 可以通过以下方式重写:

    template <class PropertyMap>
    struct vertex_visitor : public boost::dfs_visitor<>
    {
      PropertyMap m_pmap;
      vertex_visitor(PropertyMap pmap) : m_pmap(pmap) {}
      template <class Vertex, class Graph>
      void discover_vertex(Vertex v, const Graph& g)
      {
        boost::put(m_pmap, v, 42);
      }
    };
    

    这个访问者的实例化有点复杂,因为我们需要明确指定属性映射类型:

    typedef boost::property_map<graph_t, int vertex::*>::type NumbersProperty;
    vertex_visitor<NumbersProperty> vis(boost::get(&vertex::number, g));
    

    根据问题的最后一部分,图结构的突变(即添加或删除顶点和边)会使插入器无效,因此这会破坏 DFS 算法。我认为这正是图表通过 const-reference 传递的原因。

    【讨论】:

    • 哦,确实,对无效迭代器的好建议。因此,如果我需要在 DFS 中执行此操作,我每次都需要重新启动 DFS?或者有没有更好的方法来做到这一点?
    • 我认为答案取决于您要解决的问题。也许存在一种避免图形突变的算法。如果没有,那么也许您可以拥有第二个“兄弟”图并对其进行修改...
    猜你喜欢
    • 2022-08-13
    • 2023-03-21
    • 2014-08-13
    • 1970-01-01
    • 1970-01-01
    • 2012-08-14
    • 1970-01-01
    • 1970-01-01
    • 2010-10-14
    相关资源
    最近更新 更多