最短路算法简单模板

一.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. LeetCode136 Single Number, LeetCode137 Single Number II, LeetCode260 Single Number III

    136. Single Number Given an array of integers, every element appears twice except for one. Find that ...

  2. LintCode_111 爬楼梯

    题目 假设你正在爬楼梯,需要n步你才能到达顶部.但每次你只能爬一步或者两步,你能有多少种不同的方法爬到楼顶部? 比如n=3,中不同的方法 返回 3 1 2 3 5 8 13... step[2] = ...

  3. List分页

    listObj.Skip((pagecount-1)*pagesize).Take(pagesize) 假设你每页10条数据当前是第3页 跳到第4页则:listObj.Skip((4-1)*10).T ...

  4. vue 保存数组和对象, 避免双向绑定影响

    很多时候需要保存数据然后复用该数据,因vue的双向绑定总是不能保存原始数据 随笔记录解决方式 1. 不要把变量放置在data中 2. 保存至新的变量 object :   let obj= Objec ...

  5. Python中的生产者消费者模型

    ---恢复内容开始--- 了解知识点: 1.守护进程: ·什么是守护进程: 守护进程其实就是一个‘子进程’,守护即伴随,守护进程会伴随主进程的代码运行完毕后而死掉 ·为何用守护进程: 当该子进程内的代 ...

  6. hdu 6201 【树形dp||SPFA最长路】

    http://acm.hdu.edu.cn/showproblem.php?pid=6201 n个城市都在卖一种书,该书的价格在i城市为cost[i],商人打算从某个城市出发到另一个城市结束,途中可以 ...

  7. mysql原来是按自然日统计。怎么可以用今天10点到次日10点这样统计???

    关于网友提出的" mysql原来是按自然日统计.怎么可以用今天10点到次日10点这样统计???"问题疑问,本网通过在网上对" mysql原来是按自然日统计.怎么可以用今天 ...

  8. 使用 EnumWindows 找到满足你要求的窗口 - walterlv

    原文:使用 EnumWindows 找到满足你要求的窗口 - walterlv 使用 EnumWindows 找到满足你要求的窗口 2019-04-30 13:11 在 Windows 应用开发中,如 ...

  9. ROW_NUMBER(),不允许并列名次、相同值名次不重复,结果如123456……

    将score按ID分组排名:row_number() over(partition by id order by score desc) 将score不分组排名:row_number() over(o ...

  10. Vue.js 第4章 组件与路由

    组件 什么是组件:组件就是一些标签结构的封装,同时为这些结构添加需要的业务逻辑,设置你想要的样式 一个组件中一般可以设置:结构,功能和样式 为什么要使用组件: 使用方便 复用 组件的创建和使用 组件的 ...