c_cpp multiple_source_dijkstra.cpp

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c_cpp multiple_source_dijkstra.cpp相关的知识,希望对你有一定的参考价值。

#include <fstream>
#include <iterator>
#include <limits>
#include <string>
#include <random>
#include <ctime>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dijkstra_shortest_paths.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/graph/small_world_generator.hpp>
#include <boost/graph/properties.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/property_map/transform_value_property_map.hpp>
#include <boost/property_map/vector_property_map.hpp>
#include <boost/range/adaptor/filtered.hpp>
#include <boost/range/algorithm/for_each.hpp>

namespace Canard {
    template <class ParentMap, class Tag>
    struct parent_recorder : boost::base_visitor<parent_recorder<ParentMap, Tag>> {
        using event_filter = Tag;

        explicit parent_recorder(ParentMap const parent_map)
            : parent_map_(parent_map)
        {}

        template <class Edge, class Graph>
        void operator()(Edge const e, Graph const& g) const {
            auto value = get(parent_map_, source(e, g));
            put(parent_map_, target(e, g), value);
        }

    private:
        ParentMap const parent_map_;
    };

    template <class ParentMap, class Tag>
    parent_recorder<ParentMap, Tag>
    record_parent(ParentMap parent_map, Tag) {
        return parent_recorder<ParentMap, Tag>{parent_map};
    }
}

template <class Graph, class RootRange, class ParentMap, class IndexMap>
void multisource_dijkstra(Graph& graph, RootRange const root_range, ParentMap const parent_map, IndexMap const index_map)
{
    boost::dijkstra_shortest_paths(
              graph
              // root vertices
            , begin(root_range), end(root_range)
              // predecessor map(unused)
            , boost::dummy_property_map{}
              // distance map
            , boost::vector_property_map<std::size_t, IndexMap>{num_vertices(graph), index_map}
              // edge weight map(all edge weights is 1)
            , boost::make_constant_property<typename boost::graph_traits<Graph>::edge_descriptor>(1)
            , index_map
            , std::less<std::size_t>{}
            , boost::closed_plus<std::size_t>{}
            , std::numeric_limits<std::size_t>::max()
            , std::size_t{0}
            , boost::make_dijkstra_visitor(
                Canard::record_parent(parent_map, boost::on_edge_relaxed{})));
}

int main(int argc, char* argv[])
{
    using Graph = boost::adjacency_list<
          boost::vecS
        , boost::vecS
        , boost::undirectedS
        , boost::property<boost::vertex_root_t, bool>
        , boost::property<boost::edge_color_t, std::string>>;
    using SWIterator = boost::small_world_iterator<std::mt19937, Graph>;

    auto const num_v = std::size_t(100);
    auto random_gen = std::mt19937{static_cast<std::mt19937::result_type>(std::time(nullptr))};

    auto graph = Graph{SWIterator{random_gen, num_v, 4, 0.15}, SWIterator{}, num_v};


    auto const root_map = get(boost::vertex_root, graph);
    auto const index_map = get(boost::vertex_index, graph);
    using IndexMapType = decltype(index_map);
    auto const parent_map
        = boost::vector_property_map<std::string, IndexMapType>{num_vertices(graph), index_map};
    // set parent(root) and parent color
    {
        auto const root_vertices = {
            boost::vertex( 0, graph), boost::vertex(20, graph), boost::vertex(40, graph),
            boost::vertex(60, graph), boost::vertex(80, graph),
        };
        std::string const colors[] = {"tomato", "green", "cyan", "yellow", "violet"};
        auto color = colors;
        for (auto const root : root_vertices) {
            put(root_map, root, true);
            put(parent_map, root, *color++);
        }
    }


    using Vertex = boost::graph_traits<Graph>::vertex_descriptor;
    using boost::adaptors::filtered;
    multisource_dijkstra(
              graph
            , vertices(graph) | filtered([=](Vertex const v){return get(root_map, v);})
            , parent_map, index_map);


    // set edge color
    {
        using Edge = boost::graph_traits<Graph>::edge_descriptor;
        auto const edge_color_map = get(boost::edge_color, graph);
        boost::for_each(edges(graph), [&](Edge const e) {
                put(edge_color_map, e,
                    get(parent_map, source(e, graph)) == get(parent_map, target(e, graph))
                    ? get(parent_map, source(e, graph))
                    : "gray");
                });
    }

    // output to dot file
    {
        std::ofstream ofs{"graph.dot"};
        boost::dynamic_properties dp;
        dp
            .property("label", index_map)
            .property("fillcolor", parent_map)
            .property("color", get(boost::edge_color, graph))
            // emphasize root
            .property("peripheries", boost::make_transform_value_property_map(
                          [](bool const is_root){ return is_root ? 2 : 1; }
                        , get(boost::vertex_root, graph)));
        boost::write_graphviz_dp(ofs, graph, dp, "label");
    }
}

以上是关于c_cpp multiple_source_dijkstra.cpp的主要内容,如果未能解决你的问题,请参考以下文章

c_cpp 127.单词阶梯

c_cpp MOFSET

c_cpp MOFSET

c_cpp 31.下一个排列

c_cpp string→char *

c_cpp 54.螺旋矩阵