最短路-SPFA算法&Floyd算法
SPFA算法
算法复杂度
SPFA 算法是 Bellman-Ford算法 的队列优化算法的别称,通常用于求含负权边的单源最短路径,以及判负权环。
SPFA一般情况复杂度是O(m)最坏情况下复杂度和朴素 Bellman-Ford 相同,为O(nm)。
n为点数,m为边数
spfa也能解决权值为正的图的最短距离问题,且一般情况下比Dijkstra算法还好
算法步骤
queue <– 1
while queue 不为空
(1) t <– 队头
queue.pop()
(2)用 t 更新所有出边 t –> b,权值为w
queue <– b (若该点被更新过,则拿该点更新其他点)
代码实现
题目:https://www.acwing.com/problem/content/description/853/
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
ll n,m;
typedef pair<int, int> PII;
int h[maxn],e[maxn],w[maxn],ne[maxn],idx;
int dist[maxn];
bool st[maxn]; void add(int x,int y,int c)
{
//权值记录
w[idx]=c;
//终点边记录
e[idx]=y;
//存储编号为idx的边的前一条边的编号
ne[idx]=h[x];
//代表以x为起点的边的编号,这个值会发生变化
h[x]=idx++;
} ll spfa()
{
ll i,j;
memset(dist,0x3f,sizeof(dist));
dist[1]=0; queue<int> q;
//将起点加入
q.push(1);
//标记已在集合
st[1]=true;
while(q.size())
{
int t=q.front();
q.pop();
//弹出后,不在集合
st[t]=false;
for(i=h[t];i!=-1;i=ne[i])
{
//获得终点
j=e[i];
//判断距离
if(dist[j]>dist[t]+w[i])
{
//更新距离
dist[j]=dist[t]+w[i];
//判断终点是否在集合
if(!st[j])
{
//加到集合,继续更新他到其他点的最短距离
q.push(j);
st[j]=true;
}
}
}
}
//如果说原点到终点n的距离还是无穷,则代表到达不了
if(dist[n]==0x3f3f3f3f)
return -1;
else
return dist[n];
} int main()
{
ll i,j;
cin>>n>>m;
//初始化h数组为-1,目的是为ne数组赋值
memset(h,-1,sizeof(h));
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
//加边
add(x,y,z);
}
ll ans=spfa();
if(ans==-1)
cout<<"impossible";
else
cout<<ans;
return 0;
}
SPFA判断负环
求负环方法
统计当前每个点的最短路中所包含的边数,如果某点的最短路所包含的边数大于等于n,则也说明存在环。
算法步骤
①初始化要将所有点都插入到队列中
②增加一个cnt数组,来记录走的边个数
③若dist[j] > dist[t] + w[i],则表示从t点走到j点能够让权值变少,因此进行对该点j进行更新,并且对应cnt[j] = cnt[t] + 1,往前走一步
注意:该题是判断是否存在负环,并非判断是否存在从1开始的负环,因此需要将所有的点都加入队列中,更新周围的点
代码实现
题目:https://www.acwing.com/problem/content/description/854/
#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
ll n,m;
typedef pair<int, int> PII;
int h[maxn],e[maxn],w[maxn],ne[maxn],idx;
int dist[maxn],cnt[maxn];
bool st[maxn]; void add(int x,int y,int c)
{
//权值记录
w[idx]=c;
//终点边记录
e[idx]=y;
//存储编号为idx的边的前一条边的编号
ne[idx]=h[x];
//代表以x为起点的边的编号,这个值会发生变化
h[x]=idx++;
} bool spfa()
{
ll i,j;
queue<int> q;
//将所有点加入队列
for(i=1;i<=n;i++)
{
q.push(i);
st[i]=true;
}
while(q.size())
{
int t=q.front();
q.pop();
st[t]=false;
for(i=h[t];i!=-1;i=ne[i])
{
j=e[i];
//dist数组不用初始化,是因为如果为负的就进行更新,才能找出负环
if(dist[j]>dist[t]+w[i])
{
dist[j]=dist[t]+w[i];
//边数更新
cnt[j]=cnt[t]+1;
//大于n-1条边,代表有负环
if(cnt[j]>=n)
return true;
if(!st[j])
{
q.push(j);
st[j]=true;
}
}
}
}
return false;
} int main()
{
ll i,j;
cin>>n>>m;
//初始化h数组为-1,目的是为ne数组赋值
memset(h,-1,sizeof(h));
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
//加边
add(x,y,z);
}
//堆优化版的Dijkstra if(spfa())
cout<<"Yes";
else
cout<<"No";
return 0;
}
Floyd算法
原理
多源汇最短路问题
算法步骤
①初始化d
②k, i, j 去更新d
代码实现
题目:https://www.acwing.com/problem/content/description/856/
#include<bits/stdc++.h>
using namespace std;
int n,m,k;
const int maxn=220,INF=0x3f3f3f3f;
int d[maxn][maxn]; void floyd()
{ for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
}
} } int main()
{
int i,j;
cin>>n>>m>>k;
for(i=1;i<=n;i++)
{
for(j=1;j<=n;j++)
{
if(i==j)
d[i][j]=0;
else
d[i][j]=INF;
}
} while(m--)
{
int x,y,z;
cin>>x>>y>>z;
d[x][y]=min(d[x][y],z);
}
floyd(); while(k--)
{
int x,y;
cin>>x>>y;
if(d[x][y]>INF/2)
cout<<"impossible"<<endl;
else
cout<<d[x][y]<<endl;
} return 0;
}
最短路总结

最短路-SPFA算法&Floyd算法的更多相关文章
- 算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法
图论中一个经典问题就是求最短路.最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划.这也是算法中的两大经典代表.用一个简单图在纸上一步一步演算,也是 ...
- SPFA和FLOYD算法如何打印路径
早晨碰到了一题挺裸的最短路问题需要打印路径:vijos1635 1.首先说说spfa的方法: 其实自己之前打的最多的spfa是在网格上的那种,也就是二维的 一维的需要邻接表+queue 以及对于que ...
- Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较
参考 有空再更新下用c++, 下面用的Java Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV) BellmanFord:适用于权值有负值的图的单源最短路径 ...
- 多源最短路径算法—Floyd算法
前言 在图论中,在寻路最短路径中除了Dijkstra算法以外,还有Floyd算法也是非常经典,然而两种算法还是有区别的,Floyd主要计算多源最短路径. 在单源正权值最短路径,我们会用Dijkstra ...
- [链接]最短路径的几种算法[迪杰斯特拉算法][Floyd算法]
最短路径—Dijkstra算法和Floyd算法 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html Dijkstra算 ...
- 只有5行代码的算法——Floyd算法
Floyd算法用于求一个带权有向图(Wighted Directed Graph)的任意两点距离的算法,运用了动态规划的思想,算法的时间复杂度为O(n^3).具体方法是:设点i到点j的距离为d[i][ ...
- 图的最短路径算法-- Floyd算法
Floyd算法求的是图的任意两点之间的最短距离 下面是Floyd算法的代码实现模板: ; ; // maxv为最大顶点数 int n, m; // n 为顶点数,m为边数 int dis[maxv][ ...
- (转)最短路算法 -- Floyd算法
转自:http://blog.51cto.com/ahalei/1383613 暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程 ...
- 最短路径---Dijkstra/Floyd算法
1.Dijkstra算法基础: 算法过程比prim算法稍微多一点步骤,但思想确实巧妙也是贪心,目的是求某个源点到目的点的最短距离,总的来说dijkstra也就是求某个源点到目的点的最短路,求解的过程也 ...
随机推荐
- flume基本概念及相关参数详解
1.flume是分布式的日志收集系统,把手机来的数据传送到目的地去 2.flume传输的数据的基本单位是 event,如果是文本文件,通常是一行记录. event代表着一个数据流的最小完整 ...
- Date、SimpleDateFormat以及Calendar
Date类 毫秒值 java.util.Date:表示日期和时间的类 类Date表示特定的瞬间,精确到毫秒 日期转毫秒,号秒转日期 中国属于东八区,会把事件增加8个小时 1天 = 4 * 60 * 6 ...
- 风炫安全WEB安全学习第二十三节课 利用XSS获取COOKIE
风炫安全WEB安全学习第二十三节课 利用XSS获取COOKIE XSS如何利用 获取COOKIE 我们使用pikachu写的pkxss后台 使用方法: <img src="http:/ ...
- VRP OS Management
From WizNote
- 结合MATLAB、Python、R语言,在求得显著差异的边(节点对)之后,怎么画circle图
先来看看成果图: OK,开始画图: 实验背景声明:在脑影像分析中,我们首先构建脑网络,然 ...
- 【Java】集合综合案例 - 播放器管理
集合综合案例 文章目录 集合综合案例 需求分析 项目演示 详细设计 代码实现 歌曲类 播放器类 播放列表类 测试 参考资料 播放器管理 需求分析 项目演示 详细设计 代码实现 重新搞一波 复习巩固 简 ...
- 【Oracle】Oracle中chr()的含义
oracle中chr含义 CHR(10)和 CHR(13)--在oracle都为换行 chr(32)--表示空格 DECLARE v_a VARCHAR2(255); v_b VARCHAR2(255 ...
- LeetCode671. 二叉树中第二小的节点
题目 纯暴力 1 class Solution { 2 public: 3 vector<int>ans; 4 int findSecondMinimumValue(TreeNode* r ...
- misc刷题
前言:听说misc打得好,头发多不了 kali自带的字典: cd /usr/share/wordlists/ 字典网站:http://contest-2010.korelogic.com/wordli ...
- D2Admin 登录用户重新初始话右侧菜单
背景 最近用到D2Admin开发项目,用户登录菜单要根据用户角色权限获取,但是又不想用官网的方案(vue基于d2-admin的RBAC权限管理解决方案),所以自己加了个只修改 menuAside的方案 ...