在DAG中查找所有不可比较的节点

时间:2017-12-28 17:32:02

标签: boost graph directed-acyclic-graphs directed-graph

我感兴趣的是找到在有向无环图中排序的顶点集(在拓扑顺序的意义上)。

即,例如:非连接子图中的两个顶点,或者在以下情况下的对(B,C),(B,D):
a graph

我想到的天真的可能性是枚举所有拓扑排序(在这种情况下[ A, B, C, D ][ A, C, D, B ]&找到所有顺序最终在至少两种类型中不同的对,但是这个在计算上会非常昂贵。

我想要达到的目标还有其他更快的可能性吗?我正在使用boost.graph。

2 个答案:

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

渲染图:

enter image description here

摘要

无法比较具有不同颜色的分支中的节点。