最短路-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也就是求某个源点到目的点的最短路,求解的过程也 ...
随机推荐
- hive行转列,列转行
实例一:来源: https://www.cnblogs.com/kimbo/p/6208973.html 行转列 (对某列拆分,一列拆多行) 使用函数:lateral view explode(spl ...
- C#扫盲篇(三):Action和Func委托--实话实说
一.基础定义 老王想找老张的老婆出去耍,但是一看,老张还在厨房煮饭.于是老王就对老张隔壁的淑芬说:"等下老张吃完饭出去喝茶,你就把前门晒的苞谷收了,老张从左门出,你就收右边的苞谷,我就知道从 ...
- 如何将项目推到github上面
1.先查看是否安装git. 2.如果没有安装git ,下载之后别忘了配置环境变量.(右击此电脑 --属性--高级系统设置--环境变量--系统变量中的path) 3.推代码 查看状态(可查可不查) gi ...
- Go语言从入门到放弃(四)
前言 有段时间没摸Go语言了,最近B站的Go语言泄露挺火的. 还差的很远呐 学无止境 本章主要介绍一些零碎的小知识点 变更记录 # 19.4.30 起笔 # 19.4.30 增加代码打包步骤 正文 ...
- Java虚拟机常用的性能监控工具
基础故障处理工具 jps: 虚拟机进程状况工具 功能:来处正在运行的虚拟机进程,并显示虚拟机执行主类名称,以及本地虚拟机唯一ID. 它是使用频率最高的命令行工具,因为其他JDK工具大多需要输入他查询到 ...
- 如何实现一个简易版的 Spring - 如何实现 Constructor 注入
前言 本文是「如何实现一个简易版的 Spring」系列的第二篇,在 第一篇 介绍了如何实现一个基于 XML 的简单 Setter 注入,这篇来看看要如何去实现一个简单的 Constructor 注入功 ...
- Java 在windows中配置Maven环境和阿里云镜像
目录 1. 下载Maven 2. 配置环境变量 3. 配置镜像 4. 配置本地仓库 1. 下载Maven 官网:https://maven.apache.org/ 下载:apache-maven-3. ...
- 攻防世界 - Web(一)
baby_web: 1.根据题目提示,初始页面即为index,将1.php改为index.php,发现依然跳转成1.php,尝试修改抓包,出现如下回显, 2.在header中获取flag, flag: ...
- ctfhub技能树—信息泄露—hg泄露
打开靶机 查看页面信息 使用dvcs-ripper工具进行处理 ./rip-hg.pl -v -u http://challenge-cf630b528f6f25e2.sandbox.ctfhub.c ...
- Job for docker.service failed because start of the service was attempted too often. See "systemctl status docker.service" and "journalctl -xe" for details. To force a start use "systemctl reset-failed
安装docker时,自己添加了国内的hub.docker.com镜像 [root@ce-docker ~]# systemctl restart docker 出现以下报错:Job for docke ...