将丢失的节点添加到boost图中的邻接列表

时间:2014-12-24 08:42:29

标签: c++ boost graph io

我有一个类似于这样的txt文件:

2 

0 8 40 
39 204 238 
71 75 77 

意味着节点0应连接到节点2,节点1不应连接到任何东西(但仍应存在于图中),节点3连接到节点0,8,40;等。

我有这段代码:

typedef adjacency_list < vecS, vecS, undirectedS> Graph;
typedef typename boost::graph_traits<Graph>::vertex_iterator vertex_iterator;
typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;

while(getline(infile, line)) {
        tokenizer<> tok(line);
        for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
            int v=lexical_cast<int>(*beg);
            if (i<v){
                tie(e,inserted)=add_edge(i, v, G);
                if (!inserted) {
                    std::cout << "Unable to insert edge\n";
                }
            }
        }
        i++;
    }

它逐行读取txt文件并向图形添加边。它工作正常,但如果节点i没有邻居,它将不会出现在结果图中。最终,边数将是正确的,但顶点数将少于文件中的顶点数。

如何在图表中添加隔离节点?

节点除了数字之外没有任何其他属性(对应于txt文件中的行号)。

编辑1: 我希望在for循环之后检查是否没有插入,然后这个节点是单个的,我是一个新节点。 add_vertex不接受节点参数的问题。

while(getline(infile, line)) {
    tokenizer<> tok(line);
    int neighbors = 0;
    for(tokenizer<>::iterator beg=tok.begin(); beg!=tok.end();++beg){
        neighbors++;
        int v=lexical_cast<int>(*beg);
        if (i<v){
            tie(e,inserted)=add_edge(i, v, G);
            if (!inserted) {
                std::cout << "Unable to insert edge\n";
            }
        }
    }
    if no_new_edge {
        add_vertex(i, G);
    }
    i++;
}

2 个答案:

答案 0 :(得分:2)

typedef adjacency_list < vecS, vecS, undirectedS> Graph;

您使用vecS存储容器声明了图表类型。在这种情况下,顶点几乎不存在(它们是一个向量的索引,其大小表示顶点的数量。所有中间顶点都“虚拟”存在)。

你需要一个setS,listS等(由于顶点索引映射的原因,算法处理要复杂得多)。

  1. Live On Coliru 这个小样本演示了vecS如何做您想要的开箱即用:

    Edge added: 0 -> 2
    Number of edges: 1
    Number of vertices: 3
    Number of edges: 1
    Number of vertices: 3
    Edge added: 2 -> 8
    Edge added: 2 -> 40
    Number of edges: 3
    Number of vertices: 41
    Edge added: 3 -> 39
    Edge added: 3 -> 204
    Edge added: 3 -> 238
    Number of edges: 6
    Number of vertices: 239
    Edge added: 4 -> 71
    Edge added: 4 -> 75
    Edge added: 4 -> 77
    Number of edges: 9
    Number of vertices: 239
    
  2. 您可以通过执行以下操作轻松找到哪些节点没有边缘:

    <强> Live On Coliru

    for(auto vd : g.vertex_set())
        if (!g.out_edge_list(vd).empty())
            std::cout << "vertex " << vd << " has outgoing edges\n";
    

    输出:

    vertex 0 has outgoing edges
    vertex 2 has outgoing edges
    vertex 3 has outgoing edges
    vertex 4 has outgoing edges
    vertex 8 has outgoing edges
    vertex 39 has outgoing edges
    vertex 40 has outgoing edges
    vertex 71 has outgoing edges
    vertex 75 has outgoing edges
    vertex 77 has outgoing edges
    vertex 204 has outgoing edges
    vertex 238 has outgoing edges
    
  3. 如果您坚持明确控制创建哪些顶点,无论是否有边缘,只需根据您的喜好更改图形定义,例如:

    <强> Live On Coliru

    #include <boost/graph/adjacency_list.hpp>
    #include <sstream>
    #include <iostream>
    
    typedef boost::adjacency_list<boost::setS, boost::listS, boost::undirectedS, boost::property<boost::vertex_index_t, int> > Graph;
    typedef typename boost::graph_traits<Graph>::vertex_iterator vertex_iterator;
    typedef typename boost::graph_traits<Graph>::vertex_descriptor Vertex;
    
    int main() {
        Graph g;
        std::map<int, Graph::vertex_descriptor> vertex_map;
    
        int linenum = 0;
        std::string line;
        while (getline(std::cin, line)) {
            std::istringstream iss(line);
            for (std::istream_iterator<int> f(iss), l; f != l; ++f) {
                int v = *f;
                if (linenum < v) {
                    auto lvd = vertex_map[linenum];
                    if (lvd == g.null_vertex()) lvd = vertex_map[linenum] = boost::add_vertex(linenum, g);
    
                    auto vvd = vertex_map[v];
                    if (vvd == g.null_vertex()) vvd = vertex_map[v] = boost::add_vertex(v, g);
    
                    Graph::edge_descriptor e;
                    bool inserted;
                    boost::tie(e, inserted) = add_edge(lvd, vvd, g);
    
                    if (!inserted) {
                        std::cout << "Unable to insert edge\n";
                    }
                }
            }
    
            linenum++;
        }
    
        boost::property_map<Graph, boost::vertex_index_t>::const_type index_map(&g, boost::vertex_index);
        for(auto vd : g.vertex_set())
        {
            std::cout << "vertex " << boost::get(index_map, vd) << ": ";
            for(auto& e: g.out_edge_list(vd))
                std::cout << boost::get(index_map, e.get_target()) << " ";
            std::cout << "\n";
        }
    }
    

    打印

    vertex 0: 2 
    vertex 2: 0 8 40 
    vertex 8: 2 
    vertex 40: 2 
    vertex 3: 39 204 238 
    vertex 39: 3 
    vertex 204: 3 
    vertex 238: 3 
    vertex 4: 71 75 77 
    vertex 71: 4 
    vertex 75: 4 
    vertex 77: 4 
    

答案 1 :(得分:0)

这可能很有用: 如果你遇到一个空白行,请执行以下操作: add_vertex()

这是Boost Library详细信息的功能here

另外要指定节点编号,你必须设置属性。

Properties can be attached to the vertices or edges of an adjacency_list graph via the property interface

vertex_index_t是你应该在这里使用的属性标记。

向下滚动同一个链接,你会找到它。