《Boost》Part1 Minimum Spanning Tree

1、Boost中的最小生成树介绍

MST最小生成树,是图论中的基本算法,还有一种是最大生成树,此处暂不介绍。

最小生成树其实是最小权重生成树的简称。最小生成树包括两种常见的MST:Prim算法和Kruskal算法。第一个用于寻找最小生成树的算法由捷克科学家奥塔卡尔·布卢瓦卡提出,即Borůvka算法。

Boost库也提供了这两个算法的函数,直接调用即可。

该算法改进后用在超体素分割算法中,效果很好。既然作为图论中的算法,从名字就可以看出,用它来规划路径很好,也就是说,由于点云相对比较密集,可以生成最短直线或者曲线。

2、图论中的带权图分类

带权图分为有向和无向,无向图的最短路径又叫做最小生成树,有prime算法和kruskal算法;有向图的最短路径算法有dijkstra算法和floyd算法。

  生成树的概念:连通图G的一个子图如果是一棵包含G的所有顶点的树,则该子图称为G的生成树。 生成树是连通图的极小连通子图。所谓极小是指:若在树中任意增加一条边,则 将出现一个回路;若去掉一条边,将会使之变成非连通图。生成树各边的权 值总和称为生成树的权。权最小的生成树称为最小生成树,常用的算法有prime算法和kruskal算法。

  最短路径问题旨在寻找图中两节点之间的最短路径,常用的算法有:floyd算法和dijkstra算法。

3、无向图——prime算法

构造最小生成树一般使用贪心策略,有prime算法和kruskal算法

1)、prime算法思路:

(1)清空生成树,任取一个顶点加入生成树

(2)在那些一个端点在生成树里,另一个端点不在生成树里的边中,选取一条权最小的边,将它和另一个端点加进生成树

(3)重复步骤(2),直到所有的顶点都进入了生成树为止,此时的生成树就是最小生成树

2)、prime算法实现函数

int prime(int cur)
{int index;int sum = 0;memset(visit, false, sizeof(visit));visit[cur] = true;for(int i = 0; i < m; i ++){dist[i] = graph[cur][i];    }for(int i = 1; i < m; i ++){int mincost = INF;for(int j = 0; j < m; j ++){if(!visit[j] && dist[j] < mincost){mincost = dist[j];index = j;    }    }visit[index] = true;sum += mincost;for(int j = 0; j < m; j ++){if(!visit[j] && dist[j] > graph[index][j]){dist[j] = graph[index][j];}    }    } return sum;
} 

3)、再给出Boost中的Prim算法例子:

//#include <boost/config.hpp>
#include <iostream>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/prim_minimum_spanning_tree.hpp>int
main()
{using namespace boost;typedef adjacency_list < vecS, vecS, undirectedS,property<vertex_distance_t, int>, property < edge_weight_t, int > > Graph;typedef std::pair < int, int >E;const int num_nodes = 5;E edges[] = { E(0, 2), E(1, 3), E(1, 4), E(2, 1), E(2, 3),E(3, 4), E(4, 0)};int weights[] = { 1, 1, 2, 7, 3, 1, 1 };
#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300Graph g(num_nodes);property_map<Graph, edge_weight_t>::type weightmap = get(edge_weight, g); for (std::size_t j = 0; j < sizeof(edges) / sizeof(E); ++j) {graph_traits<Graph>::edge_descriptor e; bool inserted;tie(e, inserted) = add_edge(edges[j].first, edges[j].second, g);weightmap[e] = weights[j];}
#elseGraph g(edges, edges + sizeof(edges) / sizeof(E), weights, num_nodes);property_map<Graph, edge_weight_t>::type weightmap = get(edge_weight, g);
#endifstd::vector < graph_traits < Graph >::vertex_descriptor >p(num_vertices(g));#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300property_map<Graph, vertex_distance_t>::type distance = get(vertex_distance, g);property_map<Graph, vertex_index_t>::type indexmap = get(vertex_index, g);prim_minimum_spanning_tree(g, *vertices(g).first, &p[0], distance, weightmap, indexmap, default_dijkstra_visitor());
#elseprim_minimum_spanning_tree(g, &p[0]);
#endiffor (std::size_t i = 0; i != p.size(); ++i)if (p[i] != i)std::cout << "parent[" << i << "] = " << p[i] << std::endl;elsestd::cout << "parent[" << i << "] = no parent" << std::endl;return EXIT_SUCCESS;
}

4、无向图—— kruskal算法

(1)构造一个只含n个顶点,而边集为空的子图,若将该子图中各个顶点看成是各棵树的根节点,则它是一个含有n棵树的森林 。

(2)之后,从网的边集中选取一条权值最小的边,若该边的两个顶点分属不同的树 ,则将其加入子图,也就是这两个顶点分别所在的 两棵树合成一棵树;反之,若该边的两个顶点已落在同一棵树上,则不可取,而应该取下一条权值最小的边再试之。

(3)依次类推,直至森林只有一棵树。

kruskal算法能够在并查集的基础很快的实现。结合例子来介绍具体算法实现:北京大学ACM——SMT

该题的代码:

#include<iostream>
#include<algorithm>
using namespace std;const int size = 128;
int n;
int father[size];
int rank[size];//把每条边成为一个结构体,包括起点、终点和权值
typedef struct node
{int val;int start;int end;
}edge[SIZE * SIZE / 2];//把每个元素初始化为一个集合
void make_set()
{for(int i = 0; i < n; i ++){father[i] = i;rank[i] = 1;    }    return ;
}//查找一个元素所在的集合,即找到祖先
int find_set(int x)
{if(x != father[x]){father[x] = find_set(father[x]);    }    return father[x];
}//合并x,y所在的两个集合:利用Find_Set找到其中两个
//集合的祖先,将一个集合的祖先指向另一个集合的祖先。
void Union(int x, int y)
{x = find_set(x);    y = find_set(y);if(x == y){return ;    }if(rank[x] < rank[y]){father[x] = find_set(y);    }else{if(rank[x] == rank[y]){rank[x] ++;    }    father[y] = find_set(x);}return ;
}bool cmp(pnode a, pnode b)
{return a.val < b.val;
}int kruskal(int n) //n为边的数量
{int sum = 0;make_set();for(int i = 0; i < n; i ++){   //从权最小的边开始加进图中 if(find_set(edge[i].start) != find_set(edge[i].end)){Union(edge[i].start, edge[i].end);sum += edge[i].val;    }    }return sum;
}int main()
{while(1){scanf("%d", &n);    if(n == 0){break;    }char x, y;int m, weight;int cnt = 0;for(int i = 0; i < n - 1; i ++){cin >> x >> m; //scanf("%c %d", &x, &m);    //printf("%c %d ", x, m);for(int j = 0; j < m; j ++){cin >> y >> weight; //scanf("%c %d", &y, &weight);//printf("%c %d ", y, weight);    edge[cnt].start = x - 'A';edge[cnt].end = y - 'A';edge[cnt].val = weight;cnt ++;}}sort(edge, edge + cnt, cmp); //对边按权从小到大排序 cout << kruskal(cnt) << endl; }
} 

5、有向图—— floyd算法

floyd算法是最简单的最短路径算法,可以计算图中任意两点间的最短路径 folyd算法的时间复杂度是O(N3)。如果是一个没有边权的图,把相连的两点 间的距离设为dist[i][j] = 1,不相连的两点设为无穷大,用 floyd算法可以判断i,j两点是否有路径相连。这种效率肯定有点低,处理大量的点时,需要改进

实现函数:

void floyd()
{for(int k = 0; k < n; k ++){ //作为循环中间点的k必须放在最外一层循环 for(int i = 0; i < n; i ++){for(int j = 0; j < n; j ++){if(dist[i][j] > dist[i][k] + dist[k][j]){dist[i][j] = dist[i][k] + dist[k][j];    //dist[i][j]得出的是i到j的最短路径 }     }    }    }
}

6、有向图——dijkstra算法

用来计算从一个点到其他所有点的最短路径的算法,复杂度O(N2)。

void dijkstra(int s)   //s是起点
{memset(visit, false, sizeof(visit));
visit[s] = true;for(int i = 0; i < n; i ++){dist[i] = graph[s][i];}int index;for(int i = 1; i < n; i ++){int mincost = INF;for(int j = 0; j < n; j ++){if(!visit[j] && dist[j] < mincost){mincost = dist[j];index = j;    }    }visit[index] = true;for(int j = 0; j < n; j ++){if(!visit[j] && dist[j] > dist[index] + graph[index][j]){dist[j] = dist[index] + graph[index][j];}    }    }
}

《Boost》Part1 Minimum Spanning Tree相关推荐

  1. Minimum spanning tree HDU - 6954

    Minimum spanning tree HDU - 6954 题意: 给定n-1个点,编号从2到n,两点a和b之间的边权重为lcm(a,b).请找出它们形成的最小生成树. 2<=n<= ...

  2. Directed Minimum Spanning Tree: Chu-Liu/Edmonds Algorithm

    我们的现代数据库大作业要求实现一个图查询系统,包括基于属性的子图查询.可达性查询(可选).最短路径查询(可选).TopK最短路径查询(可选).图形化展示(可选)等功能.分成子图同构查询小组以及可达性及 ...

  3. 第十三章 ALDS1_12_A:Minimum Spanning Tree 最小生成树

    知识点 树是没有环的图 在树中,任意顶点r和顶点v之间必然存在着1条路径 生成树:拥有图G的所有顶点,并且在保证自身是树的前提下拥有尽量多的边. 最小生成树(MST):个边权值总和最小的生成树 普里姆 ...

  4. CodeForces - 609E Minimum spanning tree for each edge(最小生成树+树链剖分+线段树/树上倍增)

    题目链接:点击查看 题目大意:给出一张 n 个点和 m 条边组成的无向图,现在询问包含每一条边的最小生成树 题目分析:考虑求解次小生成树的思路: 求出最小生成树 ans 枚举每一条非树边 ( u , ...

  5. 最小生成树(MST,minimum spanning tree)

    生成树:由图生成的树,由图转化为树,进一步可用对树的相关操作来对图进行操作.最小指的是权值最小: 生成树是边的集合,如下图所示的最小生成树:MST={{a,b},{a,f},{f,c}}\text{M ...

  6. 百度之星2018资格赛t6三原色图(MST minimum spanning tree)

    ac代码: #include<bits/stdc++.h> #define per(i,a,b) for(int i=a;i<=b;i++) using namespace std; ...

  7. hdu 4408 Minimum Spanning Tree

    题目连接:点击打开链接 解法:利用kruskal算法 把图划分成森林, 同一点有相同最小的权值到别的点, 通过determinant计算树的课数. 总结:模板 + 自己不太懂 = 记录 + 重新学 代 ...

  8. HDU 4408 Minimum Spanning Tree 最小生成树计数

    http://acm.hdu.edu.cn/showproblem.php?pid=4408 题意:求最小生成树个数 题解:对于Kruskal算法,我们发现,最小生成树要想用多种方法就要有长度相同的边 ...

  9. 最小生成树(Minimum Spanning Tree)与最小树形图(Minimum Arborescence)问题

    没整理完 生成树:给图中指定一个特殊的点root,选择图中部分已有边生成一棵以root为根的生成树T. 最小生成树:在无向图中生成一棵树,含有的边的总权值要求是所有可能生成树中最小的,该树不唯一. 最 ...

最新文章

  1. 2013秋浙大远程教育计算机应用基础-9计算机多媒体技术,2013秋浙大远程教育计算机应用基础-9...
  2. Jmeter连接mysql(一)
  3. [转]sqlplus中不能上下键选择前一条命令解决方法
  4. 本人对于netty框架的一些理解,怎么与网站上的websock建立连接
  5. Spring Boot引用本地jar包
  6. UML九种图 之 包图和对象图
  7. android 按钮带图标 阴影_android中带图标的按钮(ImageButton)怎么用
  8. 运维(2班)梁瑞第五次作业
  9. Vue项目启动报错 error:cannot find module xxx
  10. yum安装软件出现的提示
  11. 带你学会区分Scheduled Thread Pool Executor 与Timer
  12. 一直接受键盘字符 接收小写字符出输出大写 接受大写输出小写 数字不输出
  13. jersey创建restful服务及调用_Jersey实现Restful服务(实例讲解)
  14. 刚毕业的大学夫妻,我含泪看完(转帖)
  15. 混淆矩阵 matlab代码示例
  16. NIVIDIA 硬解码学习3
  17. 安卓各大平台APP上架的一些总结
  18. 神武手游宠物加点方法及属性参考
  19. spf13/viper
  20. oracle 数据库存储过程编译报错PLS-00103出现符号 end-of-file在需要下列之一时

热门文章

  1. AIGC基础:从VAE到DDPM原理、代码详解
  2. 三表左连接(LEFT JOIN) — 两表之间的关系
  3. 实战——Linux定时执行Kettle的kjb文件
  4. matlab里面sin函数是角度,matlab-如何用matlab编写sin函数要求定义一 – 手机爱问
  5. 软件工程实践2017——软件产品案例分析
  6. Pr:导出设置之元数据
  7. 免费邮箱客户端设置方法大全
  8. 新教育杂志新教育杂志社新教育编辑部2023年第6期目录
  9. 一页纸项目管理pdf_项目管理,一页纸就够了
  10. jquery事件绑定的问题Uncaught TypeError: $(...).live is not a function at HTMLDocument.<anonymous> (ex5_