簡體   English   中英

通過圖權重增強深度優先訪問者最小生成樹

[英]Boost depth first visitor minimum spanning tree with graph weights

我想從具有邊緣權重的頂點創建最小生成樹,並以深度優先的順序遍歷圖形。 我可以構建圖形和最小生成樹,但是無法編寫自定義訪問者。

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

#include <vector>
#include <string>

typedef boost::property<boost::edge_weight_t, double> EdgeWeightProperty;
typedef boost::adjacency_list <
    boost::listS,
    boost::vecS,
    boost::undirectedS,
    boost::no_property,
    EdgeWeightProperty> MyGraph;

typedef MyGraph::edge_descriptor Edge;

class MyVisitor : public boost::default_dfs_visitor
{
    public:
    void tree_edge(Edge e, const MyGraph& g) const {

    }
};

void mst() {
    MyGraph g;
    boost::add_edge(0, 1, 0.7, g);
    boost::add_edge(0, 2, 0.1, g);

    boost::add_edge(1, 2, 0.3, g);
    boost::add_edge(1, 0, 0.7, g);
    boost::add_edge(1, 3, 0.8, g);
    boost::add_edge(1, 4, 0.2, g);

    boost::add_edge(2, 1, 0.3, g);
    boost::add_edge(2, 0, 0.1, g);
    boost::add_edge(2, 5, 0.1, g);
    boost::add_edge(2, 4, 0.5, g);

    boost::add_edge(3, 1, 0.8, g);

    boost::add_edge(4, 1, 0.2, g);
    boost::add_edge(4, 2, 0.5, g);

    boost::add_edge(5, 2, 0.1, g);

    std::list <Edge> spanning_tree;
    boost::kruskal_minimum_spanning_tree(g, std::back_inserter(spanning_tree));

    // the following two lines are failing
    MyVisitor vis();
    boost::depth_first_search(spanning_tree, visitor(vis));
}

int main(int argc, char** argv)
{
    mst();
    std::cin.get();
    return (0);
}

我想在自定義訪問者中訪問頂點和邊緣權重。 這可能嗎? 我看到了這篇文章: 提高最小生成樹,如何首先進行深度? 但我寧願不要建立單獨的權重圖。

此外,是否可以使用Boost工具在樹中以深度優先順序進行迭代而無需編寫自定義訪問者?

MyVisitor vis();

那是一個函數聲明。 查看最多煩人的解析

boost::depth_first_search(spanning_tree, visitor(vis));

這會在std::list<Edge>上調用圖算法。 depth_first_search 需要一個可以對正確的圖形概念建模的圖形

在此處輸入圖片說明

std :: list都不建模。

建議

您可以構建僅包含MST集中的邊緣的圖形。 您所鏈接問題的答案可以嘗試。

但是,創建同一圖的filtered_graph<>視圖似乎更加容易和有效,因此可以通過相同的機制簡單地獲得邊緣屬性。

首先,讓我們更喜歡在set<>而不是list<>獲得MST邊緣:

struct InSpanning {
    std::set<Edge> edges;
    bool operator()(Edge e) const { return edges.count(e); }
} spanning;

boost::kruskal_minimum_spanning_tree(g, std::inserter(spanning.edges, spanning.edges.end()));

你會注意到有趣的是, InSpanning 也是可以用作過濾謂詞的函數對象filtering_graph

boost::filtered_graph<MyGraph, InSpanning, boost::keep_all> mst(g, spanning, {});

現在您可以致電de DFS:

boost::depth_first_search(mst, visitor(vis));

我對訪客做了些微調整:

struct MyVisitor : boost::default_dfs_visitor {
    template <typename Graph>
    void tree_edge(Edge e, const Graph& g) {
        std::cout << "Visiting: " << e << " with weight " << get(boost::edge_weight, g, e) << "\n";
    }
};

注意:

  1. 它不再對MyGraph類型進行硬編碼(因為filtered_graph具有不同的類型)。
  2. 它打印您想查看的信息。

現場演示

生活在Coliru

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

#include <string>
#include <vector>

typedef boost::property<boost::edge_weight_t, double> EdgeWeightProperty;
typedef boost::adjacency_list<boost::listS, boost::vecS, boost::undirectedS, boost::no_property, EdgeWeightProperty>
    MyGraph;

typedef MyGraph::edge_descriptor Edge;

struct MyVisitor : boost::default_dfs_visitor {
    template <typename Graph>
    void tree_edge(Edge e, const Graph& g) {
        std::cout << "Visiting: " << e << " with weight " << get(boost::edge_weight, g, e) << "\n";
    }
};

void run_mst_test() {
    MyGraph g;
    boost::add_edge(0, 1, 0.7, g);
    boost::add_edge(0, 2, 0.1, g);

    boost::add_edge(1, 2, 0.3, g);
    boost::add_edge(1, 0, 0.7, g);
    boost::add_edge(1, 3, 0.8, g);
    boost::add_edge(1, 4, 0.2, g);

    boost::add_edge(2, 1, 0.3, g);
    boost::add_edge(2, 0, 0.1, g);
    boost::add_edge(2, 5, 0.1, g);
    boost::add_edge(2, 4, 0.5, g);

    boost::add_edge(3, 1, 0.8, g);

    boost::add_edge(4, 1, 0.2, g);
    boost::add_edge(4, 2, 0.5, g);

    boost::add_edge(5, 2, 0.1, g);

    struct InSpanning {
        std::set<Edge> edges;
        bool operator()(Edge e) const { return edges.count(e); }
    } spanning;

    boost::kruskal_minimum_spanning_tree(g, std::inserter(spanning.edges, spanning.edges.end()));

    MyVisitor vis;
    boost::filtered_graph<MyGraph, InSpanning, boost::keep_all> mst(g, spanning, {});
    boost::depth_first_search(mst, visitor(vis));
}

int main() {
    run_mst_test();
}

打印

Visiting: (0,2) with weight 0.1
Visiting: (2,1) with weight 0.3
Visiting: (1,3) with weight 0.8
Visiting: (1,4) with weight 0.2
Visiting: (2,5) with weight 0.1

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM