最短路算法(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 可用有负权 依次对所 ...
随机推荐
- 基于TCP编程的socket
什么是TCP/IP.UDP? TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域 ...
- Linux的一些简单命令操作总结
防火墙 查看防火墙状态 systemctl status iptables (或service iptables status) 关闭防火墙 systemctl stop iptables(或serv ...
- linux 查看并关闭窗口
查看端口 ps -ef | grep tomcat 关闭端口 kill -9 端口号
- JavaScript--自调用函数(小闭包)
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- VS中,卸载,移除,删除项目的区别
不说话,上图.
- 在IDEA中实战Git 合并&提交&切换&创建分支
工作中多人使用版本控制软件协作开发,常见的应用场景归纳如下: 假设小组中有两个人,组长小张,组员小袁 场景一:小张创建项目并提交到远程Git仓库 场景二:小袁从远程Git仓库上获取项目源码 场景三:小 ...
- Flutter SDK path为空导致工程打开后不显示iOS模拟器的问题
说明下问题场景,面向git编程时下载了个开源的Flutter项目 Mac系统下AndroidStudio打开工程后,发现顶部不展示iPhone模拟器 根据ide浅黄色提示提示,判断是FlutterSD ...
- Java练习 SDUT-2246_时间日期格式转换
时间日期格式转换 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 对于日期的常用格式,在中国常采用格式的是"年 ...
- SDUT-2116_数据结构实验之链表一:顺序建立链表
数据结构实验之链表一:顺序建立链表 Time Limit: 1000 ms Memory Limit: 65536 KiB Problem Description 输入N个整数,按照输入的顺序建立单链 ...
- HZOJ 旋转子段
作者的正解: 算法一:对于30%的数据: 直接枚举区间直接模拟,时间复杂度O(N3). 算法二:对于60%的数据:枚举旋转中心点,然后再枚举旋转的端点, 我们可以用O(n)的预处理求前缀和记录固定点, ...