求最短路径的多种算法实现

文章目录

  • 求最短路径的多种算法实现
    • 最短路径及性质
      • 性质
      • 边的松弛
    • Dijkstra算法
    • SPFA算法(B-F队列优化)
    • Floyd算法(多源最短路)

最短路径及性质

即找到一个顶点到另一个顶点成本最小的路径。

(稍微区分一下,就是最短路径在加权有向图内应用的比较多;然后最小生成树一般是在加权无向图内)

性质

  1. 路径是有向的。

  2. 并不是所有的顶点均可达。

    如果t并不是从s可达的,那么就不存在任何路径,更不存在最短路径。

    (但是一般的话,题目给的图都是强连通的)

  3. 最短路径不一定唯一。(很好理解)

  4. 可能会存在平行边以及自环,但是不影响。

    对平行边:我们会选择权重最小的一条边。

    对自环:除非自环权重=0,否则一般会忽略它。

边的松弛

在计算的时候,遇到新的边,通过更新得到新的最短路径。

struct Edge{int from;int to;double weight;
}
void relax(Edge e){int v = e.from;int w = e.to;if(dis[w]>dis[v]+e.weight){//最小路径经过edis[w]=dis[v]+e.weight;//更新距离edgeTo[w]=e;//更新点}//e边失效则忽略
}

放松边 v→w : 检查从 s 到 w 的最短路径是否先从 s 到 v,然后再由 v 到 w。如上述代码。

\\\\\\\\

Dijkstra算法

做了一点小优化:链式前向星以及优先队列的堆优化。

过了洛谷P3371&4479的板子。

#include <iostream>
#include <algorithm>
#include <queue>
#include <cstring>
using namespace std;
const int INF = 2147483647; //2^31-1
const int MAXN = 6000006;struct Edge {int to;//终点int w;//权值int next;//实际上是上一点
};//前向星-静态建立的邻接表struct Node { //用以建立优先队列int node;//编号int cost;//到达该编号结点的代价bool operator<(const Node &n)const {return cost > n.cost;}
};Edge edgeTo[MAXN];//与父节点
int head[MAXN];
int disTo[MAXN];//得到父节点到其他点的最短路径
int node, edge, start, cnt = 1; //点总数、边总数、起点、链式前向星计数
bool vis[MAXN];void init();//head数组初始化
void add(int from, int to, int w); //链式前向星加边
void input();
void output();
void Dijkstra(int s);int main() {input();Dijkstra(start);output();return 0;
}void init() {for (int i = 0; i < node; i++)head[i] = -1;
}void add(int from, int to, int w) {edgeTo[cnt].to = to;edgeTo[cnt].w = w;edgeTo[cnt].next = head[from]; //起始:next=-1;类似头插法,指针操作head[from] = cnt++; //起点的第一条边指向cnt}void input() {int from, to, w;init();//初始化cin >> node >> edge >> start;for (int i = 0; i < edge; i++) {cin >> from >> to >> w;add(from, to, w);}
}void output() {for (int i = 1; i <= node; i++)cout << disTo[i] << " ";
}void Dijkstra(int s) {for (int i = 1; i <= node; i++)disTo[i] = INF;//初始化disTo[s] = 0; //考虑无自环,到自身的距离是0priority_queue<Node>q;q.push(Node{s, 0});memset(vis, false, sizeof(vis));//初始化,还未访问任何点while (!q.empty()) {int u = q.top().node;//得到起点编号q.pop();if (!vis[u]) {//该点未遍历过vis[u] = true;for (int i = head[u]; i; i = edgeTo[i].next) {int &t = edgeTo[i].to;if (!vis[t] && disTo[t] > disTo[u] + edgeTo[i].w) {disTo[t] = disTo[u] + edgeTo[i].w;q.push(Node{t, disTo[t]});}}}}
}

变种:加权无向图中的单点最短路径。对于无向图:实际上就是在创建边的时候相应地创立两条方向不同、权值相同的有向边。
\\\\\\\\

SPFA算法(B-F队列优化)

BF没有指定边的放松顺序:

for(int pass=0;pass<G.V();pass++){//G.V()得到该图的顶点个数for(int v=0;v<G.V();v++){for(Edge e:G.adj(v))relax(e);//得到该顶点的所有联通的边数}
}

做的优化是:根据经验可知任意一轮中许多边的放松并不会成功;只有上一轮中的disTo[]值发生变化的顶点指出的边才能改变其他disTo[]的值。为了记录这样的顶点,使用队列。

以下的代码只摘选了部分,其他没有贴的是链式向前星以及输入输出(参考Dijstra),过了板子P3371。

queue<Node>q;
int onQ[MAXN] = {0};void init();//head数组初始化
void add(const int &, const int &, const int &); //链式前向星加边
void input();
void output();
void relax();
void SPFA(const int &);int main() {input();SPFA(start);output();return 0;}
void relax(int u) {for (int i = head[u]; i; i = edgeTo[i].next) {int &t = edgeTo[i].to;if (disTo[t] > disTo[u] + edgeTo[i].w) {disTo[t] = disTo[u] + edgeTo[i].w;if (!onQ[t]) {onQ[t] = 1;q.push(Node{t, disTo[t]});}}}
}void SPFA(const int &s) { //起点for (int i = 1; i <= node; i++)disTo[i] = INF;//初始化disTo[s] = 0; //考虑无自环,到自身的距离是0q.push(Node{s, 0});onQ[s] = 1;while (!q.empty()) {int u = q.front().node;q.pop();onQ[u] = 0;relax(u);}
}

\\\\\\\\

Floyd算法(多源最短路)

适用范围:无负权回路即可,边权可正可负。

这个不大适合那个板子题,会卡。

#include <iostream>
#include <algorithm>
#include <queue>
using namespace std;
//Floyd算法
const int INF = 0x3f3f3f3f; //2^31-1
const int MAXN = 6000;int G[MAXN][MAXN] = {0}; //邻接矩阵
int node, edge, start;void input();
void Floyd();
void output(const int &);int main() {input();//输入数据Floyd();output(start);//输出最终的结果return 0;
}void input() {for (int i = 1; i < MAXN; i++) { //初始化for (int j = 1; j < MAXN; j++)G[i][j] = INF;}int from, to, w;cin >> node >> edge >> start;for (int i = 1; i <= edge; i++) {cin >> from >> to >> w;G[from][to] = w;}
}void output(const int &s) {G[s][s] = 0;for (int i = 1; i <= node; i++)cout << G[s][i] << " ";
}void Floyd() {for (int k = 1; k <= node; k++) {for (int i = 1; i <= node; i++) {for (int j = 1; j <= node; j++)G[i][j] = min(G[i][j], G[i][k] + G[k][j]);}}
}

求最短路径的多种算法实现相关推荐

  1. 图算法——求最短路径(Dijkstra算法)

    目录 一.什么是最短路径 二.迪杰斯特拉(Dijkstra)算法 三.应用Dijkstra算法 (1) Dijkstra算法函数分析 求图的最短路径在实际生活中有许多应用,比如说在你在一个景区的某个景 ...

  2. C++floyd warshall算法求最短路径(附完整源码)

    C++floyd warshall算法求最短路径 floyd warshall算法求最短路径的完整源码(定义,实现,main函数测试) floyd warshall算法求最短路径的完整源码(定义,实现 ...

  3. “chaos”的算法--之Floyd算法详解(求最短路径)

    倘若我们要在计算机上建立一个交通咨询系统则可以采用图的结构来表示实际的交通网络.其实现最基本的功能,求出任意两点间的最短路径, 求最短路径的经典方法有很多种,最常用的便是迪杰斯特拉算法和佛洛依德(Fl ...

  4. C++迪杰斯特拉算法求最短路径

    一:算法历史 迪杰斯特拉算法是由荷兰计算机科学家狄克斯特拉于1959 年提出的,因此又叫狄克斯特拉算法.是从一个顶点到其余各顶点的最短路径算法,解决的是有向图中最短路径问题.迪杰斯特拉算法主要特点是以 ...

  5. Java图结构-模拟校园地图-迪杰斯特拉(Dijkstra)算法求最短路径 #谭子

    目录目录 一.前言 二.模拟校园地图描述 三.分析题目及相关绘图 四.代码部分 1.GraphNode类 2.Menu类(管理文字) 3.Attraction类 4.AttractionGraph类( ...

  6. matlab结束外循环,求单源最短路径的BellmanFord算法的matlab实现及其优化

    function [minD,path] = BellmanFord(w,start,terminal) %求单源最短路径的Bellman-Ford算法(图论) %调用格式:[minD,path] = ...

  7. 使用A*算法求最短路径

    图论中最短路径的求解之A*算法实现 代码链接 利用A*算法找到从A城市到B城市的最短路径,以及代价,其中A *算法中的h也就是从当前点到目标点的距离已经给出.程序要有通用性,即其中城市A.B可以为下图 ...

  8. python基于广度优先(BFS)的迪杰斯特拉(Dijkstra)算法 求最短路径

    python深度优先与广度优先的遍历算法区别 首先要理解搜索步,一个完整的搜索步包括两个处理: a) 获得当前位置上,有几条路可供选择 b) 根据选择策略,选择其中一条路,并走到下个位置 广度优先:就 ...

  9. 弗洛伊德算法(求最短路径)

    弗洛伊德算法(求最短路径) 在一个加权图中,如果想找到各个顶点之间的最短路径,可以考虑使用弗洛伊德算法. 弗洛伊德算法既适用于无向加权图,也适用于有向加权图.使用弗洛伊德算法查找最短路径时,只允许环路 ...

最新文章

  1. C++ 中隐藏DOS调用的命令行窗口
  2. linux命令 — lsof 查看进程打开那些文件 或者 查看文件给那个进程使用
  3. 硬盘温度70度正常吗_读懂固态硬盘:NVMe SSD的SMART健康数据这样看
  4. MATLAB库函数polly2trellis(卷积码生成多项式转网格图描述)的实现过程详解
  5. ad09只在一定范围内查找相似对象_23、面向对象编程
  6. Linux驱动如何在不同版本上快速迭代升级
  7. 【云速建站】表单应用
  8. 菜鸟裹裹宣布:让数十万快递小哥月入过万成为常态
  9. TreeSet有序集合
  10. Flutter实战之GetX工具类封装-GetUtils
  11. ojdbc6报红以及nested exception is org.hibernate.service.spi.ServiceException: 已解决
  12. java 分组求和_java 集合分组求和
  13. c++中的trivial
  14. 汉诺塔游戏玩法介绍(攻略和编程实现)
  15. 狼来了 【dfs】【树】
  16. 64位系统编译32位文件 -m32
  17. 棋盘dp 牛牛的DRB迷宫I
  18. 基于端口号的虚拟主机配置
  19. c#直接横向打印LocalReport
  20. JXTA v2.5技术手册

热门文章

  1. 看这里就知道ws2812B怎么用了(PWM+DMA)
  2. 利用TeamViewer实现唤醒远程电脑一例方法
  3. 【Computer Vision】基于VGG-16实现中草药分类
  4. ICNet: Information Conversion Network for RGB-D Based Salient Object Detection
  5. 浅论如何做一个漂亮的课件
  6. YUV 422转420
  7. QQ登录Banner之清明概念
  8. java序列化机制之protoStuff
  9. 洛阳地铁一号线无人驾驶_洛阳超级拖拉机I号实现无人驾驶功能
  10. ZED2跑ORB-SLAM3+双目相机、IMU联合标定+显卡驱动与cuda/cudnn安装