图论算法》关于SPFA和Dijkstra算法的两三事
本来我是想把这两个算法分开写描述的,但是SPFA其实就是Dijkstra的稀疏图优化,所以其实代码差不多,所以就放在一起写了。
因为SPFA是Dijkstra的优化,所以我想来讲讲Dijkstra。
什么是Dijkstra
Dijkstra是一种求单源最短路的基础算法,时间复杂度在不加堆优化的情况下是o(n^2)的,加了堆优化就能简化到o(nlogn),而且算法稳定性很强(从这点上来说比SPFA好多了,具体怎么好下面再讲),基础思路如下:
首先,把所有点到源的距离设为最大,然后把源加入队列,接着每次对队列首做这种操作:用邻接表找到从这个点能链到的所有所有点,接着要按大小顺序找当前距离和当前队首最近的点(这个按大小顺序就是可以用堆优化的地方),做松弛操作,松弛成功,将这个点入队,否则按大小顺序找下一条边,然后重复做松弛操作,直到当前点所有能链到的边松弛过,弹出当前点,重复以上操作,直到队列里没有其他元素。结束程序,输出单源到某点距离。
加了堆优化之后,有如此6的复杂度的Dijkstra,一般来说就是稳定单源最短路的最佳程序,但是在全图有负环的时候,Dijkstra算法就显得很无力了,在这时,我们就要用SPFA这种神奇的乱搞算法了。
什么是SPFA
SPFA算法全称是Shortest Path Faster Algorithm算法,人家都叫“Faster”了,那肯定有过人之处,基础思路如下:
首先,还是把所有点到源的距离设为最大,把源加入队列,接着每次对队首做这种操作:用邻接表找到从这个点能链到的所有所有点,然后对每条边做松弛操作,只要松弛成功,我们就判断当前松弛成功的点是否在队列,如果不在,就入队,否则就只是做松弛,然后弹出当前点,对下一点再次做以上操作,直到队列为空。
当然,和Dijkstra相比,SPFA看起来相当的乱搞,但是,对于绝大多数(稀疏)图来说,加了SLF和LLL两种优化的SPFA肯定比Dijkstra快得多(SLF和LLL就是两种决策优化,前者对于最值优化,后者是均值优化)。
顺带附上一道codevs1021的SPFA题目与代码
麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。
因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。
在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。
麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。
玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。
编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。
第一行有两个用空格隔开的数N和M,分别表示城市的数量以及城市间道路的数量。1≤N≤1000,1≤M≤N*(N-1)/2。城市用数字1至N标识,麦克在城市1中,玛丽卡在城市N中。
接下来的M行中每行包含三个用空格隔开的数A,B和V。其中1≤A,B≤N,1≤V≤1000。这些数字表示在A和城市B中间有一条双行道,并且在V分钟内是就能通过。
输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。
5 7
1 2 8
1 4 10
2 3 9
2 4 10
2 5 1
3 4 7
3 5 10
27
题解如下
这道题关键在于最优解可能会无法连通,所以我们求出最优解之后,要枚举最优解中哪条路会断,取其中最坏情况(题目所需),得答案就好,因为算次优解一定不能使数据再包括最优解的某条边,不然就和最优解一样了,所以以上方法是正确的。
贴出代码
#include<stdio.h>
struct shit{
int aim;
int get;
int next;
int lon;
}e[];
int max(int x,int y)
{
return x>y?x:y;
}
int pre[];
int d[],a,b,n,m,num,star,ass,quq[],point,head[],ans;
bool f[];
void fuck(int x,int y,int s)//建边
{
e[++point].aim=x;
e[point].lon=s;
e[point].get=y;
e[point].next=head[y];
head[y]=point;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d%d%d",&a,&b,&num);
fuck(a,b,num);
fuck(b,a,num);
}
quq[++star]=;
ass=;
f[]=true;
for(int i=;i<=n;i++)
d[i]=;
while(star<=ass)
{
for(int k=head[quq[star]];k!=;k=e[k].next)
if(d[quq[star]]+e[k].lon<d[e[k].aim])
{
d[e[k].aim]=d[quq[star]]+e[k].lon;
pre[e[k].aim]=k;//第一次的SPFA要记录路径(点的位置)
if(!f[e[k].aim])
{
quq[++ass]=e[k].aim;
f[e[k].aim]=true;
}
}
f[quq[star++]]=false;
}
ans=max(d[n],ans);
int q=n;
while(q!=)
{
a=e[pre[q]].lon;
e[pre[q]].lon=;//直接设置当前边数值极大(即设置为不连通)
if(pre[q]%==)//根据读入边的方法来双向删边
e[pre[q]+].lon=;
else
e[pre[q]-].lon=;
star=;
for(int i=;i<=ass;i++)
quq[i]=;
quq[star]=;
ass=;
f[]=true;
for(int i=;i<=n;i++)
{
d[i]=;
f[i]=false;
}
while(star<=ass)
{
for(int k=head[quq[star]];k!=;k=e[k].next)
if(d[quq[star]]+e[k].lon<d[e[k].aim])
{
d[e[k].aim]=d[quq[star]]+e[k].lon;
if(!f[e[k].aim])
{
quq[++ass]=e[k].aim;
f[e[k].aim]=true;
}
}
f[quq[star++]]=false;
}
if(d[n]!=)ans=max(d[n],ans);//如果数值就为我们设置的最大,即切去当前边的图无法连通
e[pre[q]].lon=a;
if(pre[q]%==)//复原切去的边
e[pre[q]+].lon=a;
else
e[pre[q]-].lon=a;
q=e[pre[q]].get;
}
printf("%d",ans);
return ;
}
PS:没有加LLL和SLF的主要原因是我还不会打→_→
图论算法》关于SPFA和Dijkstra算法的两三事的更多相关文章
- 图论算法(四)Dijkstra算法
最短路算法(三)Dijkstra算法 PS:因为这两天忙着写GTMD segment_tree,所以博客可能是seg+图论混搭着来,另外segment_tree的基本知识就懒得整理了-- Part 1 ...
- 单源最短路径算法——Bellman-ford算法和Dijkstra算法
BellMan-ford算法描述 1.初始化:将除源点外的所有顶点的最短距离估计值 dist[v] ← +∞, dist[s] ←0; 2.迭代求解:反复对边集E中的每条边进行松弛操作,使得顶点集V ...
- 最短路径算法-迪杰斯特拉(Dijkstra)算法在c#中的实现和生产应用
迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思想),直到扩展到终点为止 贪心算法(Greedy ...
- 图论最短路径算法总结(Bellman-Ford + SPFA + DAGSP + Dijkstra + Floyd-Warshall)
这里感谢百度文库,百度百科,维基百科,还有算法导论的作者以及他的小伙伴们...... 最短路是现实生活中很常见的一个问题,之前练习了很多BFS的题目,BFS可以暴力解决很多最短路的问题,但是他有一定的 ...
- 经典算法题每日演练——第十七题 Dijkstra算法
原文:经典算法题每日演练--第十七题 Dijkstra算法 或许在生活中,经常会碰到针对某一个问题,在众多的限制条件下,如何去寻找一个最优解?可能大家想到了很多诸如“线性规划”,“动态规划” 这些经典 ...
- 一步一步深入理解Dijkstra算法
先简单介绍一下最短路径: 最短路径是啥?就是一个带边值的图中从某一个顶点到另外一个顶点的最短路径. 官方定义:对于内网图而言,最短路径是指两顶点之间经过的边上权值之和最小的路径. 并且我们称路径上的第 ...
- 最短路经算法简介(Dijkstra算法,A*算法,D*算法)
据 Drew 所知最短路经算法现在重要的应用有计算机网络路由算法,机器人探路,交通路线导航,人工智能,游戏设计等等.美国火星探测器核心的寻路算法就是采用的D*(D Star)算法. 最短路经计算分静态 ...
- 图的最短路径-----------Dijkstra算法详解(TjuOj2870_The Kth City)
做OJ需要用到搜索最短路径的题,于是整理了一下关于图的搜索算法: 图的搜索大致有三种比较常用的算法: 迪杰斯特拉算法(Dijkstra算法) 弗洛伊德算法(Floyd算法) SPFA算法 Dijkst ...
- 图的最短路径---迪杰斯特拉(Dijkstra)算法浅析
什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...
随机推荐
- js 获取元素宽
第一种情况就是宽高都写在样式表里,就比如#div1{width:120px;}.这中情况通过#div1.style.width拿不到宽度,而通过#div1.offsetWidth才可以获取到宽度. 第 ...
- Happening in delphi world
Happy New Year! Delphi XE5 Update 2 Recent VCL enhancements New product features for old product use ...
- C 时间函数总结
头文件 time.h 处理器时间函数 clock_t clock(void) 处理器的处理时间,如可以在 main开始的地方 使用这个函数,然后再 完毕后 调用这个函数 并 减去 之前的返回值,为了 ...
- LINUX下的ssh登录之后的文件远程copy:scp命令(接前文ssh登录)
先记录参考: 1:http://www.cnblogs.com/peida/archive/2013/03/15/2960802.html 2:http://www.vpser.net/manage/ ...
- Socket通信简单实例(WCF调用Socket)
服务端: 控制台程序监听 /// <summary> /// Server /// </summary> class Program { static Socket serve ...
- 【HDU】4632 Palindrome subsequence(回文子串的个数)
思路:设dp[i][j] 为i到j内回文子串的个数.先枚举所有字符串区间.再依据容斥原理. 那么状态转移方程为 dp[i][j] = dp[i][j-1] + dp[i+1][j] - dp[i+ ...
- Delphi2010中DataSnap高级技术(转)
一. 为DataSnap系统服务程序添加描述 这几天一直在研究Delphi 2010的DataSnap,感觉功能真是很强大,现在足有理由证明Delphi7该下岗了. DataSnap有三种服务模式,其 ...
- git忽略一些提交上传的文件
在项目开发的过程中有两种文件是不需要提交的. 1.一些很重要的配置文件 包括服务器地址 账号密码 数据库密码 公私钥等等 2.一些由于开发和沙箱环境和线上环境的差异 不能使用同一个时候 需要同一个文件 ...
- git 基本操作 https://www.liaoxuefeng.com/wiki/0013739516305929606dd18361248578c67b8067c8c017b000/0013744142037508cf42e51debf49668810645e02887691000
1.创建版本库 (即仓库 repository)简单理解为一个目录,这个目录里的所有文件都可以被git管理起来,每个文件的修改删除,git都能跟踪,一边任何时刻都可以追踪历史,或者在将来某个时刻可以 ...
- java一位数组求平均值,小数
package com.c2; //注意数据类型,float public class Col {// public static void main(String[] args) { float m ...