最短路算法(floyed+Dijkstra+bellman-ford+SPFA)
最短路算法简单模板
一.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的话有两种情况:
- 由i直接到达j
- 由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)的更多相关文章
- 【最短路算法】Dijkstra+heap和SPFA的区别
单源最短路问题(SSSP)常用的算法有Dijkstra,Bellman-Ford,这两个算法进行优化,就有了Dijkstra+heap.SPFA(Shortest Path Faster Algori ...
- 最短路算法之 Dijkstra算法
Dijkstra算法 Dijkstra算法是典型最短路算法,用于计算一个节点到其它全部节点的最短路径. 主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止.Dijkstra算法能得出最短路径的最 ...
- 最短路算法之Dijkstra算法通俗解释
Dijkstra算法 说明:求解从起点到任意点的最短距离,注意该算法应用于没有负边的图. 来,看图. 用邻接矩阵表示 int[][] m = { {0, 0, 0, 0, 0, 0}, {0, 0, ...
- 【最短路算法】Dijkstra知识点&代码
代码: #include<iostream> #include<vector> #include<cstdio> #include<queue> #in ...
- ACM - 最短路 - AcWing 849 Dijkstra求最短路 I
AcWing 849 Dijkstra求最短路 I 题解 以此题为例介绍一下图论中的最短路算法.先让我们考虑以下问题: 给定一个 \(n\) 个点 \(m\) 条边的有向图(无向图),图中可能存在重边 ...
- ACM/ICPC 之 最短路径-Bellman Ford范例(POJ1556-POJ2240)
两道Bellman Ford解最短路的范例,Bellman Ford只是一种最短路的方法,两道都可以用dijkstra, SPFA做. Bellman Ford解法是将每条边遍历一次,遍历一次所有边可 ...
- Book 最短路算法
用HDU2544整理一下最近学的最短路算法 1.Dijkstra算法 原理:集合S表示已经找到最短路径的点,d[]表示当前各点到源点的距离 初始时,集合里面只有源点,当每个点u进入集合S时,用d[u] ...
- 最短路算法详解(Dijkstra/SPFA/Floyd)
新的整理版本版的地址见我新博客 http://www.hrwhisper.me/?p=1952 一.Dijkstra Dijkstra单源最短路算法,即计算从起点出发到每个点的最短路.所以Dijkst ...
- 图论算法——最短路径Dijkstra,Floyd,Bellman Ford
算法名称 适用范围 算法过程 Dijkstra 无负权 从s开始,选择尚未完成的点中,distance最小的点,对其所有边进行松弛:直到所有结点都已完成 Bellman-Ford 可用有负权 依次对所 ...
随机推荐
- Android LRUCache简介
LRU Cache数据结构的介绍可以参考前面的http://www.cnblogs.com/XP-Lee/p/3441555.html. 本文以Android LRUCache来做一个简单的介绍.我们 ...
- Apache Camel,Spring Boot 实现文件复制,转移 (转)
基本框架 Apache Camel Spring Boot Maven 开发过程 1.新建一个POM(quickstart)项目,在POM文件中添加Camel和Spring Boot的依赖 <p ...
- JavaSript中的正则表达式
正则表达式是对字符串操作的逻辑公式,表达了对字符串的一种过滤逻辑. 相对于.NET和Perl,JS对正则表达式的支持相当朴素,或者说JS的正则表达式是perl正则表达式的一个子集. 一.正则表达式引擎 ...
- bzoj1877 晨跑
Description Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑.仰卧起坐等 等,不过到目前为止,他 坚持下来的只有晨跑. 现在给出一张学校附近的地图,这张地图中包含N个 ...
- md5小工具
<?php$str = "123456";echo md5($str);?>
- 《mysql必知必会》笔记2(子查询、联接、组合查询、全文本搜索)
十四:使用子查询 1:子查询是嵌套在其他查询中的查询. 2:需要列出订购TNT2的所有客户信息,需要下面几步: a:从orderitems表中检索出包含物品TNT2的所有订单号: b:根据上一步得出的 ...
- Spark in action on Kubernetes - 存储篇(一)
前言 在上篇文章中,我们分析了Spark Operator内部的机制,今天我们会讨论一个在大数据领域中最重要的话题 - 存储.大数据已经无声无息的融入了每个人的生活中.大到旅游买房,小到外卖打车,都可 ...
- docker如何push镜像到docker hub个人的仓库
docker如何push镜像到docker hub个人的仓库 step1——找到本地镜像的ID:docker images step2——登陆Hub:docker login --username=u ...
- ansible基础☞第一条命令
我的两个测试机: 系统: ubuntu 16.04.2 ansible-master: 192.168.0.107 ansible-slave: 192.168.0.108 ansible版本: ro ...
- qt 中lineEdit->setText()输出double
在qt中需要将获取到的double 值在ui界面上显示出来,便于观察.但是lineEdit控件的setText()要求的参数是string. 所以我们先要进行转化,将double 转化为string. ...