单源最短路径算法
来源:互联网 发布:水平垂直居中 知乎 编辑:程序博客网 时间:2024/04/29 11:03
#include <iostream>#include <cstdio>#include <memory.h>#include <queue>using namespace std;struct edge{ //边 int from; //起点 int to; //终点 int cost; //花费};const int MAX_E = 10000; //最大边数const int MAX_V = 10000; //最大顶点数const int INF = 10000; //最大距离edge es[MAX_E]; //边集合int V,E; //V是顶点数,E是边数int d[MAX_V]; //最短距离//求出从顶点s到其余顶点的最短距离//该算法服从如下递推关系式://d[i] = min{d[j]+(从j到i的边的权值)|e=(j,i)∈E}//设初值,d[s] = 0,d[i] = INF//该方法仅适用于无负圈的有向图void shortpath_bellman_ford(int s){ //bellman-ford算法 for(int i = 0; i < V; ++i){ //初始化顶点距离为INF d[i] = INF; } d[s] = 0; while(true){ bool update = false; for(int i = 0; i < E; ++i){ //遍历所有边 edge e = es[i]; while(d[e.from] != INF && d[e.to] > d[e.from] + e.cost){ //如果起点不为无穷大且已有边距离大于 始边+权值的距离,则更新距离 d[e.to] = d[e.from] + e.cost; update = true; } } if(!update){ //如果循环一圈无更改值,则以求出最短距离 break; } }}//最短路径中,不会有经过同一个顶点两次,所有在没有负圈的情况下最多更新V-1次bool find_negative_loop(){ //判断是否有负圈,返回true有,false没有 memset(d, 0, sizeof(d)); for(int i = 0; i < V; ++i){ for(int j = 0; j < E; ++j){ edge e = es[j]; if(d[e.to] > d[e.from] + e.cost){ d[e.to] = d[e.from] + e.cost; //如果第V次还更新了,则证明有负圈 if(i == V - 1){ return true; } } } } return false;}int cost[MAX_V][MAX_V]; //cost[u][v]表示边e=(u,v)的权值,(不存在时,用INF表示)bool used[MAX_V]; //已用顶点,表示在确定最短路径的那个集合中//不能有负边//该算法的核心思想如下://从起点开始,算出起点到每个点的最短距离,不断加入距离最短的顶点,修改从起点到每个点的最短距离,直至所有顶点加入//以下实现算法,在第一次循环的时候会算出起点s到每一个顶点的最短距离void shortpath_dijkstra(int s){ //求从起点s出发到各个顶点的最短距离 fill(d, d + V, INF); //距离数组d初始化为INF fill(used, used + V, false);//访问数组used初始化为false d[s] = 0; //s到自己的距离设置为0 while(true){ int v = -1; //v表示距离(已使用顶点最短距离)的顶点 //从未使用过的顶点中,找出距离最短的顶点 for(int i = 0; i < V; ++i){ if(!used[i] && (v == -1 || d[i] < d[v])){ v = i; } } if(v == -1){ //如果循环一次未找到未使用过的,距离最短的值,则表示算法结束 break; } used[v] = true; //置v为已使用顶点 //更新从v->i的最短路径 for(int i = 0; i < V; ++i){ //取原有距离 或者 加入新顶点之后的距离 的最小值 d[i] = min(d[i],d[v] + cost[v][i]); } }}typedef pair<int, int> P; //first是最短距离,second是顶点的编号vector<edge> G[MAX_V]; //邻接表表示的图//不能有负边//该算法为dijkstra的优化算法//使用邻接表和最小堆void shortpath_dijkstra_optimize(int s){ ////求从起点s出发到各个顶点的最短距离 //实现最小堆,并且按P中的first从小到大取值 priority_queue<P, vector<P>, greater<P> > que; //最小堆 fill(d, d + V, INF); d[s] = 0; que.push(P(0, s)); while(!que.empty()){ //当堆不为空时 P p = que.top(); //取出堆中最小值 que.pop(); //弹出最小值 int v = p.second; //取出距离最短边对应的编号 //在访问的时候因为顶点更新,会造成同一个顶点,可能被多次加入最小堆中 if(d[v] < p.first) //如果取出距离大于最短距离则忽略 continue; for(int i = 0; i < G[v].size(); i++) { //更新该顶点到每一个邻接点的距离 edge e = G[v][i]; if(d[e.to] > d[v] + e.cost) { //如果加入v点后,到i的点距离变小 d[e.to] = d[v] + e.cost; //更新距离 que.push(P(d[e.to], e.to)); //压入这点的距离和该点的编号 } } }}int main(){//// //测试// //测试数据// /*// IN// 4 5 3// 0 1 2// 1 2 3// 2 3 5// 3 0 1// 3 1 4// OUT// 1 3 6 0// */// cin >> V >> E; //输入顶点数和边数// int s; //起始点// cin >> s;// for(int i = 0; i < E; ++i){// cin >> es[i].from >> es[i].to >> es[i].cost; //输入边属性// }// shortpath_bellman_ford(s);// for(int i = 0; i < V; ++i){// cout << d[i] << " ";// }//// //测试数据// /*// 3 4 0// 0 1 -2// 1 2 3// 2 0 -2// 0 2 4// OUT// 1// */// cout << find_negative_loop() << endl; //测试数据 /* IN 7 10 0 0 1 2 0 2 5 1 2 4 1 3 6 1 4 10 2 3 2 3 5 1 4 5 3 4 6 5 5 6 9 OUT 0 2 5 7 11 8 16 */// cin >> V >> E; //输入顶点数和边数// int s; //起始点// cin >> s;// for(int i = 0; i < V; ++i){// for(int j = 0; j < V; ++j){// cost[i][j] = INF;// }// }// for(int i = 0; i < E; ++i){// cin >> es[i].from >> es[i].to >> es[i].cost; //输入边属性// cost[es[i].from][es[i].to] = es[i].cost;// cost[es[i].to][es[i].from] = es[i].cost;// }// shortpath_dijkstra(s);// for(int i = 0; i < V; ++i){// cout << d[i] << " ";// } //测试数据 /* IN 4 0 3 1 1 2 2 3 5 2 0 1 3 2 2 0 2 3 3 3 0 5 1 2 2 3 OUT 0 1 3 3 */ cin >> V; int s; //起始点 cin >> s; edge e; //临时边 for(int i = 0; i < V; ++i){ cin >> E; //输入邻接边数 for(int i = 0; i < E; ++i){ cin >> e.to >> e.cost; //输入边属性 G[i].push_back(e); } } shortpath_dijkstra_optimize(s); for(int i = 0; i < V; ++i){ cout << d[i] << " "; } return 0;}
0 0
- 单源最短路径算法(Dijkstra算法)
- 单源最短路径算法(BellmanFord算法)
- Dijstra算法 单源最短路径算法
- 贪婪算法---单源最短路径
- 单源最短路径算法
- 单源最短路径 dijkstra算法
- 单源最短路径Dijkstra算法
- Dijkstra 单源最短路径算法
- 单源最短路径 :Dijkstra 算法
- (贪心算法)单源最短路径
- 单源最短路径 Dijkastra算法
- 单源最短路径(Dijkstra算法)
- 图算法---单源最短路径
- 单源最短路径----------Dijkstra算法
- 单源最短路径Dijkstra算法
- 单源最短路径(Dijkstra算法)
- 单源最短路径 : Dijkstra 算法
- Dijkstra单源最短路径算法
- Linux中VMware虚拟机增加磁盘空间的扩容操作
- Null和Undefined类型
- socket 初探
- (八)Spark源码理解之DAGScheduler---part3
- 花生壳的使用,发现是深坑
- 单源最短路径算法
- Java Timer 定时器的使用
- 国内云平台创业-企业梯队
- QT5入门之11 - 工具栏
- STM32F103ZE uIP DM9051 SPI以太网移植指南
- MFC界面控件增加鼠标浮动上去的提示功能:CToolTipCtrl
- MyBatis一对多问题记录
- Cocoa中的设计模式(MVC模式\委托模式\键值观察模式)
- Cg per-vertex lighting