图论算法》关于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)算法浅析
什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...
随机推荐
- Android 进阶14:源码解读 Android 消息机制( Message MessageQueue Handler Looper)
不要心急,一点一点的进步才是最靠谱的. 读完本文你将了解: 前言 Message 如何获取一个消息 Messageobtain 消息的回收利用 MessageQueue MessageQueue 的属 ...
- VS 2010 转到COFF期间失败。
可能的原因是framework 版本不匹配,我卸载4.5,装4.0后就解决了
- HDU - 233 Matrix
原题地址:http://acm.hdu.edu.cn/showproblem.php?pid=5015 解题思路:一看到题目,感觉是杨辉三角形,然后用组合数学做,不过没想出来怎么做,后来看数据+递推思 ...
- python 不同版本下载资源
Unofficial Windows Binaries for Python Extension Packages by Christoph Gohlke, Laboratory for Fluore ...
- bzoj 3202 [Sdoi2013]项链——容斥+置换+推式子
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3202 可见Zinn博客:https://www.cnblogs.com/Zinn/p/100 ...
- loj 572 Misaka Network 与求和 —— min_25筛
题目:https://loj.ac/problem/572 推式子:https://www.cnblogs.com/cjoieryl/p/10150718.html 又学习了一下杜教筛hh: 原来 u ...
- Winform判断是否已启动
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.W ...
- sql注入笔记
来源:https://blog.csdn.net/u011781521/article/details/57083482 这个工作上遇到了个实例: 在input框里 输入 kear' 页面 报错,出 ...
- java里的MouseLisetener接口的使用过程==========需要用组件是来注册侦听器
总结:通过匿名类来实现鼠标的监听或者 通过实现接口的方法都可以的 从此是实现MouseListener接口的方式 package com.a.b; import java.awt.Color; im ...
- memcache常见问题及解答
memcached的cache机制是怎样的? Memcached主要的cache机制是LRU(最近最少用)算法+超时失效.当您存数据到memcached中,可以指定该数据在缓存中可以呆多久Which ...