最短路算法简单模板

一.floyed算法

首先对于floyed算法来说就是最短路径的动态规划解法,时间复杂度为O(n^3) 适用于图中所有点与点之间的最短路径的算法,一般适用于点n较小的情况。

Floyed算法有三层循环,循环的层次先后顺序也是比较重要的,分别为k ,i,j;因为dis[k][i][j]代表的是i节点到j节点的最短路如果中间经过节点k的话dis[k][i][j] =dis[k-1][i][k]+dis[k-1][k][j];否则dis[k][i][j] = dis[k-1][i][j];所以说我们要求第k个节点的话就必须先把所有的k-1求出来。而此处的三维dis数组正如背包问题一样优化为二维数组。

对于任意两个节点i,j来说;要想从节点i到达节点j的话有两种情况:

  1. 由i直接到达j
  2. 由i经过若干个k节点到达j

所以dis[i][j] = min(dis[i][j],dis[i][k]+dis[k][j]);

HDU 2544 最短路

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2544

 #include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f;
int n, m, mp[][];
void floyed()
{
for (int k = ; k <= n; k++)
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
mp[i][j] = min(mp[i][j], mp[i][k] + mp[k][j]);
}
int main()
{
ios::sync_with_stdio(false);
while ((cin >> n >> m)&&n&&m) {
memset(mp, INF, sizeof(mp));
for (int a, b, c, i = ; i < m; i++) {
cin >> a >> b >> c;
mp[a][b] = mp[b][a] = min(mp[a][b], c);
}
floyed();
cout << mp[][n] << endl;
}
return ;
}

二.Dijkstra算法

关于Dijkstra算法(贪心)的推断过程我就不详细的讲啦,我会的别人都已经讲完了而且还比我详细,在这里向大家推荐一篇写的不错的博客!https://www.cnblogs.com/nigang/p/3658990.html

这位博主讲的还是很详细的,图解也很清晰明了

下面我还是通过一个例题来讲解代码吧!(同floyed例题)

邻接矩阵的Dijkstra:

 #include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int INF = 0x3f3f3f;
int n, m, mp[][];
int dis[], vis[];
void Dijkstra()
{
for (int i = ; i <= n; i++) {
vis[i] = ; dis[i] = mp[][i];
}
for (int i = ; i <= n; i++) {
int cnt = INF, k;
for (int j = ; j <= n; j++) {
if (!vis[j] && dis[j] < cnt) {
cnt = dis[j];
k = j;
}
}
vis[k] = ;
for (int j = ; j <= n; j++) {
if (!vis[j] && dis[j] > dis[k] + mp[k][j])
dis[j] = dis[k] + mp[k][j];
}
}
}
int main()
{
ios::sync_with_stdio(false);
while ((cin >> n >> m)&&n&&m) {
memset(mp, INF, sizeof(mp));
for (int a, b, c, i = ; i < m; i++) {
cin >> a >> b >> c;
mp[a][b] = mp[b][a] = min(mp[a][b], c);
}
Dijkstra();
cout << dis[n] << endl;
}
return ;
}

堆优化后的Dijkstra

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<bitset>
#include<vector>
#include<queue> using namespace std;
const int INF = << ;
const int maxn = ;
struct node{
int to, cost;
node() {}
node(int a, int b) :to(a), cost(b) {}
bool operator<(const node&a)const {
if (cost == a.cost)return to < a.to;
return cost > a.cost;
}
};
vector<node>e[maxn];
int n, m, dis[maxn];
void Dijkstra(int s)
{
for (int i = ; i <= n; i++)dis[i] = INF;
dis[s] = ;
priority_queue<node>Q;
Q.push(node(s, dis[s]));
while (!Q.empty()) {
node t = Q.top(); Q.pop();
for (int i = ; i < e[t.to].size(); i++) {
int tmp = e[t.to][i].to;
if (dis[tmp] > t.cost + e[t.to][i].cost) {
dis[tmp] = t.cost + e[t.to][i].cost;
Q.push(node(tmp, dis[tmp]));
}
}
}
}
int main()
{
ios::sync_with_stdio(false);
while ((cin >> n >> m)&&(n&&m)) {
for (int i = ; i <= n; i++)e[i].clear();
for (int a, b, c, i = ; i < m; i++) {
cin >> a >> b >> c;
e[a].push_back(node(b, c));
e[b].push_back(node(a, c));
}
Dijkstra();
cout << dis[n] << endl;
}
return ;
}

三.bellman-ford算法

当路径当中出现负权值边的时候Dijkstra算法将不再适用,因为dijkstra由于是贪心的,每次都找一个距源点最近的点,然后将该距离定为这个点到源点的最短路径,但如果存在负权边,那就有可能先通过并不是距源点最近的一个次优点,而是这一个负权值边,所求出的结果可能就不是最短距离了。

算法讲解https://blog.csdn.net/niushuai666/article/details/6791765

模板:无向图。有向图的话边只需要加一次即可

 #include<iostream>
#include<algorithm> using namespace std;
const int INF = << ;
const int maxn = ;
struct node {
int from, to, cost;
node() {}
node(int a, int b, int c) :from(a), to(b), cost(c) {}
}e[maxn<<];
int n, m, dis[];
bool bellman_ford()
{
for (int i = ; i <= n; i++)dis[i] = INF;
dis[] = ;
for (int i = ; i < n; i++) {
int flag = ;
for (int j = ; j <= * m; j++) {
if (dis[e[j].to] > dis[e[j].from] + e[j].cost) {
dis[e[j].to] = dis[e[j].from] + e[j].cost;
flag = ;
}
}
if (!flag)return true;
}
for (int j = ; j <= m; j++)
if (dis[e[j].to] > dis[e[j].from] + e[j].cost)
return false;
return true;
}
int main()
{
ios::sync_with_stdio(false);
while ((cin >> n >> m)&&n&&m) {
for (int a, b, c, i = ; i <= m; i++) {
cin >> a >> b >> c;
e[i] = node(a, b, c);
e[i + m] = node(b, a, c);
}
bellman_ford();
cout << dis[n] << endl;
}
return ;
}

四. SPFA 算法<--bellman-ford算法的优化

一篇清晰的算法过程的讲解!https://www.cnblogs.com/bofengyu/p/5004398.html

代码模板如下

例题:POJ 2387

http://poj.org/problem?id=2387

 #include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#include<queue> using namespace std;
const int maxn = ;
const int INF = 0x3f3f3f3f3f;
int n, m;
struct node{
int to, cost;
node() {}
node(int a, int b) :to(a), cost(b) {}
};
vector<node> e[maxn];
int vis[maxn], f[maxn], dis[maxn];
void SPFA(int s)
{
for (int i = ; i < maxn; i++) {
vis[i] = ; f[i] = ;
dis[i] = INF;
}
dis[s] = ;
vis[s] = ; f[s]++;
queue<int>Q;
Q.push(s);
while (!Q.empty()) {
int t = Q.front(); Q.pop();
vis[t] = ;
for (int i = ; i < e[t].size(); i++) {
int tmp = e[t][i].to;
if (dis[tmp] > dis[t] + e[t][i].cost) {
dis[tmp] = dis[t] + e[t][i].cost;
if (!vis[tmp]) {
vis[tmp] = ;
Q.push(tmp);
if (++f[tmp] > n)return;
}
}
}
}
return;
}
int main()
{
ios::sync_with_stdio(false);
while (cin >> m >> n) {
for (int a, b, c, i = ; i <= m; i++) {
cin >> a >> b >> c;
e[a].push_back(node(b, c));
e[b].push_back(node(a, c));
}
SPFA();
cout << dis[n] << endl;
}
return ;
}

最短路算法(floyed+Dijkstra+bellman-ford+SPFA)的更多相关文章

  1. 【最短路算法】Dijkstra+heap和SPFA的区别

    单源最短路问题(SSSP)常用的算法有Dijkstra,Bellman-Ford,这两个算法进行优化,就有了Dijkstra+heap.SPFA(Shortest Path Faster Algori ...

  2. 最短路算法之 Dijkstra算法

    Dijkstra算法 Dijkstra算法是典型最短路算法,用于计算一个节点到其它全部节点的最短路径. 主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法能得出最短路径的最 ...

  3. 最短路算法之Dijkstra算法通俗解释

    Dijkstra算法 说明:求解从起点到任意点的最短距离,注意该算法应用于没有负边的图. 来,看图. 用邻接矩阵表示 int[][] m = { {0, 0, 0, 0, 0, 0}, {0, 0, ...

  4. 【最短路算法】Dijkstra知识点&代码

    代码: #include<iostream> #include<vector> #include<cstdio> #include<queue> #in ...

  5. ACM - 最短路 - AcWing 849 Dijkstra求最短路 I

    AcWing 849 Dijkstra求最短路 I 题解 以此题为例介绍一下图论中的最短路算法.先让我们考虑以下问题: 给定一个 \(n\) 个点 \(m\) 条边的有向图(无向图),图中可能存在重边 ...

  6. ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)

    两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可 ...

  7. Book 最短路算法

    用HDU2544整理一下最近学的最短路算法 1.Dijkstra算法 原理:集合S表示已经找到最短路径的点,d[]表示当前各点到源点的距离 初始时,集合里面只有源点,当每个点u进入集合S时,用d[u] ...

  8. 最短路算法详解(Dijkstra/SPFA/Floyd)

    新的整理版本版的地址见我新博客 http://www.hrwhisper.me/?p=1952 一.Dijkstra Dijkstra单源最短路算法,即计算从起点出发到每个点的最短路.所以Dijkst ...

  9. 图论算法——最短路径Dijkstra,Floyd,Bellman Ford

    算法名称 适用范围 算法过程 Dijkstra 无负权 从s开始,选择尚未完成的点中,distance最小的点,对其所有边进行松弛:直到所有结点都已完成 Bellman-Ford 可用有负权 依次对所 ...

随机推荐

  1. C++程序设计教材目录思维导图(增C++Primer)

    正在做C++思维导图,大工程,比较艰苦. 先做了三个C++教材目录的思维导图.C++教材不等于C++,这个容易些.看思维导图,整理所学知识,这个可以会. 给出三张图,对应三种教材: 谭浩强. C++程 ...

  2. could not insert: [com.trs.om.bean.UserLog] The user specified as a definer ('root'@'127.0.0.1') does not exist

    2019-07-01 11:24:09,315 [http-8080-24] org.hibernate.util.JDBCExceptionReporter logExceptionsWARN: S ...

  3. 总结 ESP8266 RTOS 开发环境搭建

    总结 ESP8266 RTOS 开发环境搭建 仔细看官方文档. 必须一步一步操作. 不要想当然,以为 make 就可以. 忽略编译警告,除非是错误. 工具链必须使用官方提供的. 多看看 Issues ...

  4. python Python程序的架构

  5. Codeforces 414B

    题目链接 附上代码: #include<cstdio> #include<cstring> #include<bits/stdc++.h> #define mod ...

  6. poj3294 后缀数组

    后缀数组多个字符串问题. 先求出height[]数组,然后二分求最大的长度. 但是条件需要改变.如果出现次数大于一般那就满足.然后就要解决如何判断那一段属于其中一个字符串. 所以先处理出长度.并且不断 ...

  7. jsp项目中整个项目没有问题但是servlet报错

    项目没问题但是serverlet报错 项目右键 buildPath-->configure build path -->Myeclipse Library-->J2EE 1.3 Li ...

  8. 关于inflate的第3个参数

    关于inf 方法 inflate(int resource, ViewGroup root, boolean attachToRoot) 中,前连个参数都好理解,我比较费解的是第3个参数. 文档中的解 ...

  9. celery琐碎笔记

    -l 指定日志等级 -n 指定任务名称 -Q 指定任务执行队列 -c 指定启动celery的cpu数量 --logfile 指定日志输出到文件,会输出任务函数里的print,而控制台不会,用于调试. ...

  10. ansible基础☞安装方法

    一 需要安装些什么 Ansible默认通过 SSH 协议管理机器. 安装Ansible之后,不需要启动或运行一个后台进程,或是添加一个数据库.只要在一台电脑(可以是一台笔记本)上安装好,就可以通过这台 ...