最短路算法简单模板

一.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. Directx11教程(46) alpha blend(3)

    原文:Directx11教程(46) alpha blend(3)       现在我们尝试改变box的贴图,使用一张带alpha的dds文件wirefence.dds, 用directx textu ...

  2. Directx11教程(35) 纹理映射(5)

    原文:Directx11教程(35) 纹理映射(5)     到现在为止,我们的TextureClass初始化函数非常简单,说白了就是一行代码: result = D3DX11CreateShader ...

  3. parkingLot

    一个支付宝停车支付生活号前端页面 //index.html //自定义键盘 <!DOCTYPE html> <html> <head> <meta chars ...

  4. SQL Server 记录(更新中...)

    sys.databases 显示所有数据库信息 sys.tables 显示当前数据库所有的表的信息 Go 向 SQL Server 实用工具发出一批 Transact-SQL 语句已结束的信号,Go本 ...

  5. css的两栏布局

    经典的实现左边固定宽度,右边宽度自适应的几种方法 利用float和margin-left属性(margin-left的值可以稍稍大于或者等于.left的宽度) .left{ width: 30px; ...

  6. hdu 1503 LCS输出路径【dp】

    hdu 1503 不知道最后怎么输出,因为公共部分只输出一次.有人说回溯输出,感觉好巧妙!其实就是下图,输出的就是那条灰色的路径,但是初始时边界一定要初始化一下,因为最第一列只能向上走,第一行只能向左 ...

  7. nodeJs学习-02 fs模块(文件操作)

    读文件: const fs = require('fs'); //读文件(异步) readFile(文件名,回调函数) fs.readFile('section03/testData/aaa.txt' ...

  8. HDU 5673 Robot【卡特兰数】

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5673 题意: 有一个机器人位于坐标原点上.每秒钟机器人都可以向右移到一个单位距离,或者在原地不动.如 ...

  9. python 清空文件夹

    #!/usr/bin/env python# -*- coding:utf-8 -*-import os def del_file(path): for i in os.listdir(path): ...

  10. java根据年月获取当前月的每一天日期

    public static List<String> getDayByMonth(int yearParam,int monthParam){         List list = ne ...