我感兴趣的是找到在有向无环图中排序的顶点集(在拓扑顺序的意义上)。
即,例如:非连接子图中的两个顶点,或者在以下情况下的对(B,C),(B,D):
我想到的天真的可能性是枚举所有拓扑排序(在这种情况下[ A, B, C, D ]
和[ A, C, D, B ]
&找到所有顺序最终在至少两种类型中不同的对,但是这个在计算上会非常昂贵。
我想要达到的目标还有其他更快的可能性吗?我正在使用boost.graph。
答案 0 :(得分:2)
基本上你想要的是一对节点(u,v)
,这样就没有从u到v的路径,也没有从v到u的路径。您可以为每个节点查找使用DFS从该节点可访问的所有节点。总复杂度O(n(n+m))
。
现在你要做的就是每一对检查两个节点是否都不能被另一个节点访问。
答案 1 :(得分:1)
您可以从简单的拓扑排序开始。 Boost的实现方便地返回一个反向排序的顶点列表。
您可以迭代该列表,使用新的分支ID标记每个初始叶节点,直到遇到共享节点。
让我们从图模型的简单开始:
#include <boost/graph/adjacency_list.hpp>
using Graph = boost::adjacency_list<>;
我们希望映射分支:
using BranchID = int;
using BranchMap = std::vector<BranchID>; // maps vertex id -> branch id
我们想要构建,映射和可视化映射:
Graph build();
BranchMap map_branches(Graph const&);
void visualize(Graph const&, BranchMap const& branch_map);
int main() {
// sample data
Graph g = build();
// do the topo sort and distinguish branches
BranchMap mappings = map_branches(g);
// output
visualize(g, mappings);
}
来自问题的示例数据:
Graph build() {
Graph g(4);
enum {A,B,C,D};
add_edge(A, B, g);
add_edge(A, C, g);
add_edge(C, D, g);
return g;
}
如导言中所述:
#include <boost/graph/topological_sort.hpp>
std::vector<BranchID> map_branches(Graph const& g) {
std::vector<Vertex> reverse_topo;
boost::topological_sort(g, back_inserter(reverse_topo));
// traverse the output to map to unique branch ids
std::vector<BranchID> branch_map(num_vertices(g));
BranchID branch_id = 0;
for (auto v : reverse_topo) {
auto degree = out_degree(v, g);
if (0 == degree) // is leaf?
++branch_id;
if (degree < 2) // "unique" path
branch_map[v] = branch_id;
}
return branch_map;
}
让我们用每个分支着色的图形表示:
#include <boost/graph/graphviz.hpp>
#include <iostream>
void visualize(Graph const& g, BranchMap const& branch_map) {
// display helpers
std::vector<std::string> const colors { "gray", "red", "green", "blue" };
auto name = [](Vertex v) -> char { return 'A'+v; };
auto color = [&](Vertex v) -> std::string { return colors[branch_map.at(v) % colors.size()]; };
// write graphviz:
boost::dynamic_properties dp;
dp.property("node_id", transform(name));
dp.property("color", transform(color));
write_graphviz_dp(std::cout, g, dp);
}
这使用一个微小的速记助手来创建转换属性贴图:
// convenience short-hand to write transformed property maps
template <typename F>
static auto transform(F f) { return boost::make_transform_value_property_map(f, boost::identity_property_map{}); };
要在非c ++ 14编译器上编译它,您可以用扩展正文替换对
transform
的调用
<强> Live On Coliru 强>
#include <boost/graph/adjacency_list.hpp>
using Graph = boost::adjacency_list<>;
using BranchID = int;
using BranchMap = std::vector<BranchID>; // maps vertex id -> branch id
Graph build();
BranchMap map_branches(Graph const&);
void visualize(Graph const&, BranchMap const& branch_map);
int main() {
// sample data
Graph g = build();
// do the topo sort and distinguish branches
BranchMap mappings = map_branches(g);
// output
visualize(g, mappings);
}
using Vertex = Graph::vertex_descriptor;
Graph build() {
Graph g(4);
enum {A,B,C,D};
add_edge(A, B, g);
add_edge(A, C, g);
add_edge(C, D, g);
return g;
}
#include <boost/graph/topological_sort.hpp>
std::vector<BranchID> map_branches(Graph const& g) {
std::vector<Vertex> reverse_topo;
boost::topological_sort(g, back_inserter(reverse_topo));
// traverse the output to map to unique branch ids
std::vector<BranchID> branch_map(num_vertices(g));
BranchID branch_id = 0;
for (auto v : reverse_topo) {
auto degree = out_degree(v, g);
if (0 == degree) // is leaf?
++branch_id;
if (degree < 2) // "unique" path
branch_map[v] = branch_id;
}
return branch_map;
}
#include <boost/property_map/transform_value_property_map.hpp>
// convenience short-hand to write transformed property maps
template <typename F>
static auto transform(F f) { return boost::make_transform_value_property_map(f, boost::identity_property_map{}); };
#include <boost/graph/graphviz.hpp>
#include <iostream>
void visualize(Graph const& g, BranchMap const& branch_map) {
// display helpers
std::vector<std::string> const colors { "gray", "red", "green", "blue" };
auto name = [](Vertex v) -> char { return 'A'+v; };
auto color = [&](Vertex v) -> std::string { return colors[branch_map.at(v) % colors.size()]; };
// write graphviz:
boost::dynamic_properties dp;
dp.property("node_id", transform(name));
dp.property("color", transform(color));
write_graphviz_dp(std::cout, g, dp);
}
打印
digraph G {
A [color=gray];
B [color=red];
C [color=green];
D [color=green];
A->B ;
A->C ;
C->D ;
}
渲染图:
无法比较具有不同颜色的分支中的节点。