提升 BGL BFS 查找从源到目标的所有唯一路径
Boost BGL BFS Find all unique paths from Source to Target
我正在使用 Boost BGL C++,我需要图形来执行从源顶点到目标顶点的 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;
}
输入(顶点 1、顶点 2、权重):
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
输出(源 = 0,目标 = 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
我不会使用 BFS 算法,因为它使用颜色图来跟踪访问过的节点。但是,如果您想要所有不同的路径,则不希望跳过已访问过的节点(因为您可能会跳过替代路径)。
相反,我将实现一种蛮力广度优先递归算法,该算法只需访问所有相邻节点,除非它们已经在当前路径中。
所需的所有状态都是当前路径。
这里更详细地解释了这个想法:https://www.quora.com/How-should-I-find-all-distinct-simple-paths-between-2-given-nodes-in-an-undirected-graph
住在科里鲁
#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
相关文章:
- 何时在引用或唯一指针上使用移动语义
- C++优先级队列,按对象的唯一指针的特定方法升序排列
- 如何将更多文件夹添加到c++include路径
- 计算排序向量的向量中唯一值的计数
- 带有特殊路径部分的"std::filesystem::weakly_canonical"失败
- C++A*算法并不总是在路径中具有目标节点
- 如何使用Visual Studio 2017在C++中为参数化对象数组使用唯一指针
- 从函数角度看ID到文件路径的内部与外部映射
- 通过组合不同的类型来创建唯一的id
- 使用Unique_ptr确保工厂中的对象唯一
- c++多进程编写一个唯一的文件
- boost xml parsingl将xml的路径作为变量发送
- 在以唯一ptr为值的C++映射中,动态内存何时会被销毁
- 对于MacOS上的G++,如何添加默认的include目录/usr/local/include和默认的库搜索路径/usr
- 如何使用cppcheck处理半相对包含路径
- 我的递归算法中的问题,用于查找所有最短、唯一的路径
- 提升 BGL BFS 查找从源到目标的所有唯一路径
- 如何将目录路径转换为唯一的数字标识符 (Linux/C++)
- 如何生成唯一的文件名或路径
- 查找网格上唯一路径的数量