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算法的更多相关文章

  1. 算法学习笔记(三) 最短路 Dijkstra 和 Floyd 算法

    图论中一个经典问题就是求最短路.最为基础和最为经典的算法莫过于 Dijkstra 和 Floyd 算法,一个是贪心算法,一个是动态规划.这也是算法中的两大经典代表.用一个简单图在纸上一步一步演算,也是 ...

  2. SPFA和FLOYD算法如何打印路径

    早晨碰到了一题挺裸的最短路问题需要打印路径:vijos1635 1.首先说说spfa的方法: 其实自己之前打的最多的spfa是在网格上的那种,也就是二维的 一维的需要邻接表+queue 以及对于que ...

  3. Dijkstra、Bellman_Ford、SPFA、Floyd算法复杂度比较

    参考 有空再更新下用c++, 下面用的Java Dijkstra:适用于权值为非负的图的单源最短路径,用斐波那契堆的复杂度O(E+VlgV) BellmanFord:适用于权值有负值的图的单源最短路径 ...

  4. 多源最短路径算法—Floyd算法

    前言 在图论中,在寻路最短路径中除了Dijkstra算法以外,还有Floyd算法也是非常经典,然而两种算法还是有区别的,Floyd主要计算多源最短路径. 在单源正权值最短路径,我们会用Dijkstra ...

  5. [链接]最短路径的几种算法[迪杰斯特拉算法][Floyd算法]

    最短路径—Dijkstra算法和Floyd算法 http://www.cnblogs.com/biyeymyhjob/archive/2012/07/31/2615833.html Dijkstra算 ...

  6. 只有5行代码的算法——Floyd算法

    Floyd算法用于求一个带权有向图(Wighted Directed Graph)的任意两点距离的算法,运用了动态规划的思想,算法的时间复杂度为O(n^3).具体方法是:设点i到点j的距离为d[i][ ...

  7. 图的最短路径算法-- Floyd算法

    Floyd算法求的是图的任意两点之间的最短距离 下面是Floyd算法的代码实现模板: ; ; // maxv为最大顶点数 int n, m; // n 为顶点数,m为边数 int dis[maxv][ ...

  8. (转)最短路算法 -- Floyd算法

    转自:http://blog.51cto.com/ahalei/1383613        暑假,小哼准备去一些城市旅游.有些城市之间有公路,有些城市之间则没有,如下图.为了节省经费以及方便计划旅程 ...

  9. 最短路径---Dijkstra/Floyd算法

    1.Dijkstra算法基础: 算法过程比prim算法稍微多一点步骤,但思想确实巧妙也是贪心,目的是求某个源点到目的点的最短距离,总的来说dijkstra也就是求某个源点到目的点的最短路,求解的过程也 ...

随机推荐

  1. MAC与ARP缓存中毒介绍

    ARP 协议 用于地址解析,请求MAC地址. arp -a 或者 -n 查看ARP缓存表 ls(ARP) 查看scapy里的协议字段 ARP缓存中毒原理 ARP收到ARP请求报文,会将发送方的mac地 ...

  2. 十八般武艺玩转GaussDB(DWS)性能调优:SQL改写

    摘要:本文将系统介绍在GaussDB(DWS)系统中影响性能的坏味道SQL及SQL模式,帮助大家能够从原理层面尽快识别这些坏味道SQL,在调优过程中及时发现问题,进行整改. 数据库的应用中,充斥着坏味 ...

  3. day121:MoFang:植物的状态改动(幼苗→成长期)&植物的浇水功能

    目录 1.当果树种植以后在celery的异步任务中调整浇水的状态 2.客户端通过倒计时判断时间,显示浇水道具 3.客户端判断当前种植物状态控制图标的显示和隐藏 4.当用户单击浇水图标, 则根据当前果树 ...

  4. 安装Linux Deploy和Termux之后,再安装ftp服务软件都是多余的!

    之前以为Debian 9 running via Linux Deploy或者Termux在安卓系统部署之后,一定要安装vsftpd或者pure-ftpd这些专门的ftp服务器软件,才能提供ftp服务 ...

  5. Nginx集成Naxsi防火墙

    前言 因工作原因,接触到了WAF,今天部署了一下Naxsi,记录一下 GitHub 正文 环境 Centos 7 下载 更新yum yum update -y 安装必要依赖 yum install g ...

  6. Flutter 基础组件:图片和Icon

    前言 Flutter中,可以通过Image组件来加载并显示图片,Image的数据源可以是asset.文件.内存以及网络. ImageProvider 是一个抽象类,主要定义了图片数据获取的接口load ...

  7. 简单解析一下 Mybatis 常用的几个配置

    目录 核心配置文件 环境配置(environments) 属性(properties) 类型别名(typeAliases) 映射器(mappers) Mybatis 参考:https://mybati ...

  8. 攻防世界—pwn—hello_pwn

    题目分析 下载文件后首先使用checksec检查文件保护机制 使用ida查看伪代码 思路明确,让dword_60106C == 1853186401即可输出flag 信息收集 偏移量 sub_4006 ...

  9. online创建索引中途取消导致索引无法删除解决办法

    问题:有一个表ID栏位没有索引,但是在一个update语句的where中被使用,因此打算online创建索引,但是长时间没有成功,此时决定取消,取消后发现索引无法删除 过程: 数据库监控报警有行锁,进 ...

  10. 理解C#中的 async await

    前言 一个老掉牙的话题,园子里的相关优秀文章已经有很多了,我写这篇文章完全是想以自己的思维方式来谈一谈自己的理解.(PS:文中涉及到了大量反编译源码,需要静下心来细细品味) 从简单开始 为了更容易理解 ...