BGL自定义权重,求dijkstra
图graph
BGL有3种保存图的数据结构,分别是adjacency_list
,adjacency_matrix
和CSR(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{ //边的信息,假设权重是自定义类型Testint x=1;int y=1;} w; struct less {bool operator() (const Test& x, const Test & y) const {return x.x<y.x;}typedef Test first_argument_type;typedef Test second_argument_type;typedef bool result_type;}; struct closed_plus//保证加法不越界{const Test inf;closed_plus() : inf({10000,10000}) { }closed_plus(Test inf) : inf(inf) { }Test operator()(const Test& a, const Test& b) const {using namespace std;if (a.x == inf.x && a.y == inf.y) return inf;if (b.x == inf.x && b.y == inf.y) return inf;return {a.x+b.x,a.y+ b.y};}}; friend std::ostream& operator << (std::ostream& x, const Test q); }; std::ostream& operator << (std::ostream& x, const udi::TopoEdgeProperty::Test q){return x<<"("<<q.x<<" ,"<<q.y<<")"; }
那么定义的图的方法如下
typedef boost::adjacency_list<boost::listS , //边的保存方案,用listboost::vecS , //点的保存方案,用vector,可以下标访问boost::directedS , //undirectedSudi::TopoVertexProperty, //自定义vertexudi::TopoEdgeProperty> Graph; //自定义edgetypedef 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 , bool>EdgeDescriptor e;bool bbb;boost::tie(e,bbb) = boost::add_edge( v1 , v2 , udi::TopoEdgeProperty(), g);std::pair<EdgeDescriptor , bool> e21 = boost::add_edge(v2 , v1 , g);std::pair<EdgeDescriptor , bool> e23 = boost::add_edge(v2 , v3 , g);std::pair<EdgeDescriptor , bool> e34 = boost::add_edge(v3 , v4 , g);std::pair<EdgeDescriptor , bool> e41 = boost::add_edge(v4 , v1 , g);std::pair<EdgeDescriptor , bool> e13 = boost::add_edge(v1 , v2 , g);std::pair<EdgeDescriptor , bool> 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<Graph>::vertex_iterator it;auto index_map = boost::get(boost::vertex_index, g);std::vector<VertexDescriptor > predecessor_map(num_vertices(g));std::vector<udi::TopoEdgeProperty::Test> 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), //weightindex_map,udi::TopoEdgeProperty::less(),udi::TopoEdgeProperty::closed_plus(),udi::TopoEdgeProperty::Test({10000,10000}), //infudi::TopoEdgeProperty::Test({0,0}), //zeroboost::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<Graph>::vertex_iterator it;source = boost::vertex(1,g); std::vector<float> 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<VertexDescriptor > 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]));
BGL自定义权重,求dijkstra相关推荐
- 自定义函数求圆和圆柱体的表面积
本题要求自定义函数求圆和圆柱体的表面积. 自定义两个area函数,一个形参的实现求圆的面积,两个形参的实现求圆柱体的表面积.PI是全局符号常量. 函数接口定义: double area(double ...
- 自定义函数求一元二次方程C语言版
题目 1028: [编程入门]自定义函数求一元二次方程 时间限制: 1Sec 内存限制: 128MB 题目描述 求方程 的根,用三个函数分别求当b^2-4ac大于0.等于0.和小于0时的根,并输出结果 ...
- C语言:1027.自定义函数求最大公约数和最小公倍数
C语言:1027.自定义函数求最大公约数和最小公倍数 题目描述: 写两个函数,分别求两个整数的最大公约数和最小公倍数,用主函数调用这两个函数,并输出结果两个整数由键盘输入. 解题思路: 1.利用辗转相 ...
- 自定义函数求两个整数的和
一.自定义函数的构成: 自定义函数就是根据需要自己定义的函数,他的作用就是帮助我们实现我们想实现的功能.在定义函数时,需要注意以下几点: 1.函数名不可忽略.一个函数必须又一个合法的函数名,函数命名时 ...
- 一元函数求导C语言,自定义函数求一元二次方程(C语言版)
注意点: 输出的格式,多少位后小数. scanf后要记得加& <0的情况要记得分类 题目描述 求方程 的根,用三个函数分别求当b^2-4ac大于0.等于0.和小于0时的根,并输出结果.从 ...
- C++自定义sobel求梯度
Mat Sobel_gradient(Mat img, int direction) {Mat oriImage = img;Mat newImage_x = Mat(img.size(), CV_8 ...
- [编程入门]自定义函数求一元二次方程
题目描述 求方程 的根,用三个函数分别求当b^2-4ac大于0.等于0.和小于0时的根,并输出结果.从主函数输入a.b.c的值. 输入 a b c 输出 x1=? x2=? 样例输入 4 1 1 样例 ...
- 自定义函数求一元二次方程(C语言)
题目: 求方程的根,用三个函数分别求当b^2-4ac大于0.等于0.和小于0时的根,并输出结果.从主函数输入a.b.c的值. 一般式:ax²+bx+c=0(a≠0) 其中a是二次项系数,b是一次项系数 ...
- 题目 1028: 自定义函数求一元二次方程
题目描述 求方程 的根,用三个函数分别求当b^2-4ac大于0.等于0.和小于0时的根,并输出结果.从主函数输入a.b.c的值. 输入 a b c 输出 x1=? x2=? 样例输入 4 1 1 样例 ...
最新文章
- 【Smart_Point】C/C++ 中智能指针
- VASP计算HSE06带隙INCAR
- Bzoj3550 [ONTAK2010]Vacation
- “非”天才女程序员的人生
- React Native 实现FlatList的下拉刷新上拉加载
- Java NIO系列教程(十 五)Java NIO Path
- 服务器虚拟化相关问题分析,服务器虚拟化后引入的问题分析
- 毕设日志5.12凌晨
- dc综合与pt静态时序分析(中文)_新能源汽车小三电系统(PDU/DC/OBC)技术研究详解...
- 计算机系统端口445,如何关闭445端口,教您如何关闭系统端口
- xp系统下硬盘安装linux,在NTFS格式硬盘XP下安装LINUX系统
- URP——后期处理特效——通道混合器Channel Mixer
- 微信小程序模板消息测试- formId 的获取
- java 多字段分组_在Java 8中按多个字段名称分组
- Linux中如何让命令在后台运行
- nmap -oG -iL 写入文件和读取文件之[网鼎杯 2020 朱雀组]Nmap
- 北大考研复试上机——W's Cipher
- Calendar类(日历)
- 如何选购计算机硬件,DIY攒机经验之谈:十年老司机教你组装电脑如何选购硬件...
- 欧式几何—功能游戏介绍