BGL自定义权重,求dijkstra

图graph

BGL有3种保存图的数据结构,分别是adjacency_list,adjacency_matrixCSR(compressed_sparse_row_graph)就是中文对应的我觉得是前向星。我觉得CSR挺垃圾的(黑一波),所以尽量不要使用(而且是不是可变图Mutable Graph,太垃圾了!)。

这里主要介绍adjacency_list的使用。adjacency_list的定义有若干个参数

boost::adjacency_list<     
     boost::listS,          // 出边的数据类型
     boost::vecS,           // 保存顶点的数据类型
     boost::undirectedS,    // 边的类型(单向、双向等)
     boost::no_property,    // 顶点的其他特性(权重,或者ID之类)
     boost::no_property,    // 边的其他特性
     boost::no_property,    // 图对象的特性
     boost::listS>          // 保存边的容器类型(暂时不知道和第一个参数是否冲突或类似)

 

图有顶点vertex,和边edge。我们可以自定义两种数据类型。

namespace udi{
struct TopoVertexProperty{    //自定义顶点
  //std::string label;
  int32_t vertex_id;
  float position_x;
  float position_y;
  float position_z;
  struct qqq{int xyz;}gg;
};
​
struct TopoEdgeProperty{   //自定义边
 public:
  float weight = 1;        //边的信息
  float weight2 = 3;       //边的信息
  struct Test{             //边的信息,假设权重是自定义类型Test
    int x=1;
    int y=1;
  } w;
​
  struct less {
    bool operator() (const Test& x, const Test & y) const {
      return x.x 
  

那么定义的图的方法如下

  typedef boost::adjacency_list Graph;  //自定义edge
  typedef Graph::edge_descriptor EdgeDescriptor; //描述边的类型
  typedef Graph::vertex_descriptor VertexDescriptor; //描述点的类型
  Graph g;

添加点的方法如下

  VertexDescriptor v1 = boost::add_vertex(udi::TopoVertexProperty(), g); //可以直接带上数值来直接给点赋值。
  VertexDescriptor v2 = boost::add_vertex(g);
  VertexDescriptor v3 = boost::add_vertex(g);
  VertexDescriptor v4 = boost::add_vertex(g);
  VertexDescriptor v5 = boost::add_vertex(g);
​
//给顶点赋值
​
//集合赋值法
  auto vertexs =  boost::get(&udi::TopoVertexProperty::gg, g); //得到的是g里所有顶点里gg的属性的集合
  vertexs[v1].xyz= 5;  //直接赋值
​
//直接访问的方法给顶点赋值
 g[v1].vertex_id = 0; g[v1].position_x = 11; g[v1].position_y = 111; g[v1].position_z = 11111111;
  g[v2].vertex_id = 1; g[v2].position_x = 22; g[v2].position_y = 222; g[v2].position_z = 22222222;
  g[v3].vertex_id = 2; g[v3].position_x = 33; g[v3].position_y = 333; g[v3].position_z = 33333333;
  g[v4].vertex_id = 3; g[v4].position_x = 44; g[v4].position_y = 444; g[v4].position_z = 44444444;
  g[v5].vertex_id = 4; g[v5].position_x = 55; g[v5].position_y = 555; g[v5].position_z = 55555555;

 

添加边与给边赋值的方法

 auto q = boost::add_edge(1,4,udi::TopoEdgeProperty(), g);
  //std::pair
  EdgeDescriptor e;
  bool bbb;
  boost::tie(e,bbb)  = boost::add_edge( v1 , v2 , udi::TopoEdgeProperty(), g);
  std::pair e21 = boost::add_edge(v2 , v1 , g);
  std::pair e23 = boost::add_edge(v2 , v3 , g);
  std::pair e34 = boost::add_edge(v3 , v4 , g);
  std::pair e41 = boost::add_edge(v4 , v1 , g);
  std::pair e13 = boost::add_edge(v1 , v2 , g);
  std::pair e25 = boost::add_edge(v2 , v5 , g);
  g[q.first].weight = 4;

 

输出调试信息,边,点等信息。

std::cout << "Graph:" << std::endl;
  boost::print_graph(g , boost::get(  &udi::TopoVertexProperty::vertex_id, g) );
//上面的print_graph函数,并不能特别优雅的进行输出...也许我方法不对。
  std::cout << "num_vertex:" << boost::num_vertices(g) << std::endl;
  std::cout << "num_edges:" << boost::num_edges(g) << std::endl;
​

 

Dijkstra方法求最短路

boost::graph_traits::vertex_iterator it;
  auto index_map = boost::get(boost::vertex_index, g);
  std::vector predecessor_map(num_vertices(g));
  std::vector distances(boost::num_vertices(g));//距离数组的类型,必须和权重的类型一致。这里我们用的是Test类型(大多数时候是float之类的)
  auto distance_iterator = boost::make_iterator_property_map(distances.begin() , boost::get(boost::vertex_index , g));
​
source = boost::vertex(1,g);
  boost::dijkstra_shortest_paths(g,
                                 source,
                                 &predecessor_map[0],
                                 distance_iterator,//&distances[0]都行吗?
                                 boost::get(&udi::TopoEdgeProperty::w ,g), //weight
                                 index_map,
                                 udi::TopoEdgeProperty::less(),
                                 udi::TopoEdgeProperty::closed_plus(),
                                 udi::TopoEdgeProperty::Test({10000,10000}), //inf
                                 udi::TopoEdgeProperty::Test({0,0}), //zero
                                 boost::default_dijkstra_visitor()
                                );
​
​
//输出调试信息
  std::cout << "distances and parents:" << std::endl;
​
  Graph::vertex_iterator vi, vend;
  for (boost::tie(vi, vend) = boost::vertices(g); vi != vend; ++ vi) {
    std::cout << "distance(" << g[*vi].vertex_id <<")=" << distances[*vi] << ",";
    std::cout << "parent(" << g[*vi].vertex_id <<")=" << g[predecessor_map[*vi]].vertex_id<< std::endl;
  }

 

有时候不是自定义类型,是系统类型为权重(比如float,double等),耶就是说不需要提供比较器之类的东西,此时可以用下面的方法来进行求解Dijkstra最短路。

//以float为例
boost::graph_traits::vertex_iterator it;
  source = boost::vertex(1,g);
​
  
  std::vector distances(boost::num_vertices(g));
  auto weight_map=boost::weight_map(boost::get(&udi::TopoEdgeProperty::weight ,g));
  auto index_map = boost::get(boost::vertex_index, g);
  std::vector predecessor_map(num_vertices(g));
  auto distance_iterator = boost::make_iterator_property_map(distances.begin() , boost::get(boost::vertex_index , g));
  
​
  boost::dijkstra_shortest_paths(g, source,
                                 weight_map.
                                     distance_map(distance_iterator).
                                     predecessor_map(&predecessor_map[0]));

 

你可能感兴趣的:(水)