Boost BGL BFS查找从源到目标的所有唯一路径 我使用Boost BGL C++,我需要图表来做一个从源顶点到目标顶点的BFS,并返回所有唯一的路径。

Boost BGL BFS查找从源到目标的所有唯一路径 我使用Boost BGL C++,我需要图表来做一个从源顶点到目标顶点的BFS,并返回所有唯一的路径。,c++,boost,graph,C++,Boost,Graph,现在,我想到了一种使用过滤图获得包含源到目标路径的图子集的方法,但我意识到它基本上不是过滤的,因为过滤图包括访问的顶点,但不是源到目标路径的一部分。有没有办法获得这些信息,或者采用不同的方法更好 参考代码: boost::filtered_graph<DirectedGraph, boost::keep_all, std::function<bool(VertexDescr)>> Graph::getUniquePathsFromSource(VertexDescr so

现在,我想到了一种使用过滤图获得包含源到目标路径的图子集的方法,但我意识到它基本上不是过滤的,因为过滤图包括访问的顶点,但不是源到目标路径的一部分。有没有办法获得这些信息,或者采用不同的方法更好

参考代码:

boost::filtered_graph<DirectedGraph, boost::keep_all, std::function<bool(VertexDescr)>> Graph::getUniquePathsFromSource(VertexDescr source, VertexDescr target, DirectedGraph const & g)
{
    std::vector<double> distances(num_vertices(g));
    std::vector<boost::default_color_type> colormap(num_vertices(g));

    // Run BFS and record all distances from the source node
    breadth_first_search(g, source,
        visitor(make_bfs_visitor(boost::record_distances(distances.data(), boost::on_tree_edge())))
        .color_map(colormap.data())
    );

    for (auto vd : boost::make_iterator_range(vertices(g)))
        if (colormap.at(vd) == boost::default_color_type{})
            distances.at(vd) = -1;

    distances[source] = -2;

    boost::filtered_graph<DirectedGraph, boost::keep_all, std::function<bool(VertexDescr)>>
        fg(g, {}, [&](VertexDescr vd) { return distances[vd] != -1; });

    // Print edge list
    std::cout << "filtered out-edges:" << std::endl;
    std::cout << "Source Vertex: " << source << std::endl;

    auto ei = boost::edges(fg);

    typedef boost::property_map<DirectedGraph, boost::edge_weight_t>::type WeightMap;
    WeightMap weights = get(boost::edge_weight, fg);

    for (auto it = ei.first; it != ei.second; ++it)
    {
        if (source != boost::target(*it, g)) {
            std::cout << "Edge Probability " << *it << ": " << get(weights, *it) << std::endl;
        }
    }

    return fg;
}
输出(源=0,目标=5):

预期产出:

0->1->5
0->3->4->705->5
0->2->3->4->705->5

我不会使用BFS算法,因为它使用彩色贴图来跟踪访问的节点。但是,如果需要所有不同的路径,则不希望跳过已访问的节点(因为您可能会跳过其他路径)

相反,我将实现一个蛮力广度优先递归算法,它只访问所有相邻节点,除非它们已经在当前路径中

所需的所有状态都是当前路径

这里将更详细地解释这一想法:

#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp> // print_graph
using namespace boost;
using Graph = adjacency_list<vecS, listS, directedS, property<vertex_index_t, int>, property<edge_weight_t, double> >;
Graph read_graph();

using Vertex = Graph::vertex_descriptor;
using Path = std::vector<Vertex>;

template <typename Report>
void all_paths_helper(Vertex from, Vertex to, Graph const& g, Path& path, Report const& callback) {
    path.push_back(from);

    if (from == to) {
        callback(path);
    } else {
        for (auto out : make_iterator_range(out_edges(from, g))) {
            auto v = target(out, g);
            if (path.end() == std::find(path.begin(), path.end(), v)) {
                all_paths_helper(v, to, g, path, callback);
            }
        }
    }

    path.pop_back();
}

template <typename Report>
void all_paths(Vertex from, Vertex to, Graph const& g, Report const& callback) {
    Path state;
    all_paths_helper(from, to, g, state, callback);
}

int main() {
    auto g = read_graph();
    print_graph(g, std::cout);

    auto by_vertex_id = [&](int id) {
        return *find_if(vertices(g), [&](Vertex vd) { return id == get(vertex_index, g, vd); });
    };

    all_paths(by_vertex_id(0), by_vertex_id(5), g, [&](Path const& path) {
            std::cout << "Found path ";
            for (auto v : path)
                std::cout << get(vertex_index, g, v) << " ";
            std::cout << "\n";
        });
    std::cout.flush();
}

// immaterial to the task, reading the graph
Graph read_graph() {
    std::istringstream iss(R"(
        0 1 0.001
        0 2 0.1
        0 3 0.001
        1 5 0.001
        2 3 0.001
        3 4 0.1
        1 482 0.1
        482 635 0.001
        4 705 0.1
        705 5 0.1
        1 1491 0.01
        1 1727 0.01
        1 1765 0.01)");

    Graph g;
    auto vertex = [&,idx=std::map<int,Vertex>{}](int id) mutable {
        auto it = idx.find(id);
        if (it != idx.end())
            return it->second;
        return idx.emplace(id, add_vertex(id, g)).first->second;
    };

    for (std::string line; getline(iss, line);) {
        std::istringstream ls(line);
        int s,t; double w;
        if (ls >> s >> t >> w) {
            add_edge(vertex(s), vertex(t), w, g);
        } else {
            std::cerr << "Skipped invalid line '" << line << "'\n";
        }
    }

    return g;
}

+答案是1!我继续使用您的解决方案,没有使用
auto by_vertex_id=[&](int id){return*find_if(顶点(g),[&](顶点vd){return id==get(顶点索引,g,vd);}据我所知,这检查顶点索引是否等于顶点描述符?您需要一些东西来找到源/目标顶点的描述符,对吗?如果你想更常规地拼写它(主要是,更少的lambda):甚至。C++确实有了长途跋涉,我明白了,我对lambda公约是比较新的,所以我仍然在学习它。谢谢
0->1->5
0->3->4->705->5
0->2->3->4->705->5
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/graph_utility.hpp> // print_graph
using namespace boost;
using Graph = adjacency_list<vecS, listS, directedS, property<vertex_index_t, int>, property<edge_weight_t, double> >;
Graph read_graph();

using Vertex = Graph::vertex_descriptor;
using Path = std::vector<Vertex>;

template <typename Report>
void all_paths_helper(Vertex from, Vertex to, Graph const& g, Path& path, Report const& callback) {
    path.push_back(from);

    if (from == to) {
        callback(path);
    } else {
        for (auto out : make_iterator_range(out_edges(from, g))) {
            auto v = target(out, g);
            if (path.end() == std::find(path.begin(), path.end(), v)) {
                all_paths_helper(v, to, g, path, callback);
            }
        }
    }

    path.pop_back();
}

template <typename Report>
void all_paths(Vertex from, Vertex to, Graph const& g, Report const& callback) {
    Path state;
    all_paths_helper(from, to, g, state, callback);
}

int main() {
    auto g = read_graph();
    print_graph(g, std::cout);

    auto by_vertex_id = [&](int id) {
        return *find_if(vertices(g), [&](Vertex vd) { return id == get(vertex_index, g, vd); });
    };

    all_paths(by_vertex_id(0), by_vertex_id(5), g, [&](Path const& path) {
            std::cout << "Found path ";
            for (auto v : path)
                std::cout << get(vertex_index, g, v) << " ";
            std::cout << "\n";
        });
    std::cout.flush();
}

// immaterial to the task, reading the graph
Graph read_graph() {
    std::istringstream iss(R"(
        0 1 0.001
        0 2 0.1
        0 3 0.001
        1 5 0.001
        2 3 0.001
        3 4 0.1
        1 482 0.1
        482 635 0.001
        4 705 0.1
        705 5 0.1
        1 1491 0.01
        1 1727 0.01
        1 1765 0.01)");

    Graph g;
    auto vertex = [&,idx=std::map<int,Vertex>{}](int id) mutable {
        auto it = idx.find(id);
        if (it != idx.end())
            return it->second;
        return idx.emplace(id, add_vertex(id, g)).first->second;
    };

    for (std::string line; getline(iss, line);) {
        std::istringstream ls(line);
        int s,t; double w;
        if (ls >> s >> t >> w) {
            add_edge(vertex(s), vertex(t), w, g);
        } else {
            std::cerr << "Skipped invalid line '" << line << "'\n";
        }
    }

    return g;
}
1 --> 5 482 1491 1727 1765 
0 --> 1 2 3 
2 --> 3 
3 --> 4 
5 --> 
4 --> 705 
482 --> 635 
635 --> 
705 --> 5 
1491 --> 
1727 --> 
1765 --> 
Found path 0 1 5 
Found path 0 2 3 4 705 5 
Found path 0 3 4 705 5