首页 文章

Boost BGL BFS查找从Source到Target的所有唯一路径

提问于
浏览
3

我正在使用Boost BGL C,我需要Graph从Source顶点到目标顶点执行BFS并返回所有唯一路径 .

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

代码:

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;
}

输入(vertex1,vertex2,weight):

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

输出(For Source = 0,Target = 5):

Source Vertex: 0
Edge Probability (0,1): 0.001
Edge Probability (0,2): 0.1
Edge Probability (0,3): 0.001
Edge Probability (1,5): 0.001
Edge Probability (1,482): 0.1
Edge Probability (1,1491): 0.01
Edge Probability (1,1727): 0.01
Edge Probability (1,1765): 0.01
Edge Probability (2,3): 0.001
Edge Probability (3,4): 0.1
Edge Probability (4,705): 0.1
Edge Probability (482,635): 0.001
Edge Probability (705,5): 0.1

预期产出:

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

1 回答

  • 2

    我不会使用BFS算法,因为它使用色彩映射来跟踪被访问的节点 . 但是,如果您想要所有不同的路径,则不希望跳过已访问过的节点(因为您可能会跳过备用路径) .

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

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

    这个想法在这里有更详细的解释:https://www.quora.com/How-should-I-find-all-distinct-simple-paths-between-2-given-nodes-in-an-undirected-graph

    Live On Coliru

    #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
    

相关问题