通过与输入相同的提升图创建无向图

Posted

技术标签:

【中文标题】通过与输入相同的提升图创建无向图【英文标题】:Create undirected graph by boost graph same as the input 【发布时间】:2014-06-01 10:55:30 【问题描述】:

我想创建如下图,第一列是顶点,其他的是邻接顶点

1 2 3 4 7 2 1 3 4 3 1 2 4 4 1 2 3 5 5 4 6 7 8 6 5 7 8 7 1 5 6 8 8 5 6 7

我像这样将边添加到图中

using MinCutG = boost::adjacency_list<boost::vecS, boost::vecS, boost::undirectedS>;

MinCutG graph;
std::vector<std::vector<int> > input 1,2,3,4,7, 2,1,3,4, 3,1,2,4,
            4,1,2,3,5, 5,4,6,7,8, 6,5,7,8, 7,1,5,6,8, 8,5,6,7;
for(auto const &data : input)
    auto begin = std::begin(data);
    auto end = std::end(data);
    if(begin != end)
        auto const Vertex = *begin;
        ++begin;
        while(begin != end)
            boost::add_edge(Vertex, *begin, graph);        
            ++begin;
        
    

打印图表

template<typename Graph>
void print_adjacent_vertex(Graph const &g)

    for (auto vertex = vertices(g); vertex.first != vertex.second; ++vertex.first)
        std::cout << *vertex.first << " is connected with ";
        for (auto neighbour = adjacent_vertices(*vertex.first, g);
             neighbour.first != neighbour.second; ++neighbour.first)
            std::cout << *neighbour.first << " ";
        
        std::cout<<std::endl;
    

我希望输出应该与输入相同,但事实并非如此 结果是

1 与 2 3 4 7 2 3 4 7 相连 2与1 1 3 4 3 4相连 3与1 2 1 2 4 4相连 4与1 2 3 1 2 3 5 5相连 5与4 4 6 7 8 6 7 8相连 6与5 5 7 8 7 8相连 7与1 5 6 1 5 6 8 8相连 8与5 6 7 5 6 7相连

我的预期结果

1与2 3 4 7相连 2与1 3 4相连 3与1 2 4相连 4与1 2 3 5相连 5与4 6 7 8相连 6与6 5 7 8相连 7 与 7 1 5 6 8 相连 8 与 8 5 6 7 相连

【问题讨论】:

【参考方案1】:

简而言之,将setS 用于OutEdgeList 模板参数将禁用平行边,从而产生所需的输出。

boost::adjacency_list 的第一个模板参数是OutEdgeList,它控制某些图形行为,例如允许或禁止平行边。在无向MinCutG 图的情况下,vecS 用作OutEdgeList,这将启用平行边。例如,如果一个无向图支持平行边,那么:

add_edge(1, 2, graph); // Vertex 1 and 2 are adjacent to one another via edge A.
add_edge(2, 1, graph); // Vertex 1 and 2 are adjacent to one another via edge B,
                       // which is parallel to edge A.

顶点1adjacent_vertices() 将包含两次顶点2,每条边一次(AB)。

如documentation 中所述,可以通过对OutEdgeList 使用setShash_setS 选择器来禁用平行边。例如,改变:

using MinCutG = boost::adjacency_list<
  boost::vecS, // OutEdgeList with parallel edges
  boost::vecS,
  boost::undirectedS>;

到:

using MinCutG = boost::adjacency_list<
  boost::setS, // OutEdgeList with no parallel edges
  boost::vecS,
  boost::undirectedS>;

这是一个使用原始代码的example,只是将OutEdgeListvecS更改为setS

#include <iostream>
#include <vector>
#include <boost/graph/adjacency_list.hpp>

template<typename Graph>
void print_adjacent_vertex(Graph const &g)

    for (auto vertex = vertices(g); vertex.first != vertex.second; 
         ++vertex.first)
        std::cout << *vertex.first << " is connected with ";
        for (auto neighbour = adjacent_vertices(*vertex.first, g);
             neighbour.first != neighbour.second; ++neighbour.first)
            std::cout << *neighbour.first << " ";
        
        std::cout<<std::endl;
    


int main()

    using MinCutG = boost::adjacency_list<
        boost::setS, boost::vecS, boost::undirectedS>;

    MinCutG graph;
    std::vector<std::vector<int> > input
    
        1,2,3,4,7,
        2,1,3,4,
        3,1,2,4,
        4,1,2,3,5,
        5,4,6,7,8,
        6,5,7,8,
        7,1,5,6,8,
        8,5,6,7
    ;

    for(auto const &data : input)
        auto begin = std::begin(data);
        auto end = std::end(data);
        if(begin != end)
            auto const Vertex = *begin;
            ++begin;
            while(begin != end)
                boost::add_edge(Vertex, *begin, graph);        
                ++begin;
            
        
    
    print_adjacent_vertex(graph);

产生以下输出:

0 is connected with 
1 is connected with 2 3 4 7 
2 is connected with 1 3 4 
3 is connected with 1 2 4 
4 is connected with 1 2 3 5 
5 is connected with 4 6 7 8 
6 is connected with 5 7 8 
7 is connected with 1 5 6 8 
8 is connected with 5 6 7

【讨论】:

【参考方案2】:

正如 Tanner 解释的那样,您基本上将每条边添加两次,首先是 (a,b),然后是 (b,a)。避免这种情况的一种但相当昂贵的方法是使用setS 作为控制边缘容器的模板参数。这就是 Tanner 在他的回答中提出的建议。

另一种方法是在添加之前检查边缘是否存在。这意味着线

boost::add_edge(Vertex, *begin, graph);   

应该替换为

if (! edge(Vertex, *begin, graph).second ) //edge does not exist yet
    boost::add_edge(Vertex, *begin, graph); 

在大多数情况下,此代码可能会更快并消耗更少的内存。

【讨论】:

以上是关于通过与输入相同的提升图创建无向图的主要内容,如果未能解决你的问题,请参考以下文章

数据结构--图

图--04---加权无向图最小生成树

用邻接表实现无向图的创建与输出

求算法,用邻接矩阵和邻接表创建一个图,实现深度和广度搜索,菜单形式,c语言的代码。无向无权的图。

数据结构无向图的建立

tarjan-无向图(求割点)