本来我是想把这两个算法分开写描述的,但是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题目与代码

  麦克找了个新女朋友,玛丽卡对他非常恼火并伺机报复。

    因为她和他们不住在同一个城市,因此她开始准备她的长途旅行。

    在这个国家中每两个城市之间最多只有一条路相通,并且我们知道从一个城市到另一个城市路上所需花费的时间。

    麦克在车中无意中听到有一条路正在维修,并且那儿正堵车,但没听清楚到底是哪一条路。无论哪一条路正在维修,从玛丽卡所在的城市都能到达麦克所在的城市。

    玛丽卡将只从不堵车的路上通过,并且她将按最短路线行车。麦克希望知道在最糟糕的情况下玛丽卡到达他所在的城市需要多长时间,这样他就能保证他的女朋友离开该城市足够远。

编写程序,帮助麦克找出玛丽卡按最短路线通过不堵车道路到达他所在城市所需的最长时间(用分钟表示)。

输入描述 Input Description

第一行有两个用空格隔开的数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分钟内是就能通过。

 

输出描述 Output Description

   输出文件的第一行中写出用分钟表示的最长时间,在这段时间中,无论哪条路在堵车,玛丽卡应该能够到达麦克处,如果少于这个时间的话,则必定存在一条路,该条路一旦堵车,玛丽卡就不能够赶到麦克处。

样例输入 Sample Input

5 7

1 2 8

1 4 10

2 3 9

2 4 10

2 5 1

3 4 7

3 5 10

样例输出 Sample Output

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

  1. 图论算法(四)Dijkstra算法

    最短路算法(三)Dijkstra算法 PS:因为这两天忙着写GTMD segment_tree,所以博客可能是seg+图论混搭着来,另外segment_tree的基本知识就懒得整理了-- Part 1 ...

  2. 单源最短路径算法——Bellman-ford算法和Dijkstra算法

     BellMan-ford算法描述 1.初始化:将除源点外的所有顶点的最短距离估计值 dist[v] ← +∞, dist[s] ←0; 2.迭代求解:反复对边集E中的每条边进行松弛操作,使得顶点集V ...

  3. 最短路径算法-迪杰斯特拉(Dijkstra)算法在c#中的实现和生产应用

    迪杰斯特拉(Dijkstra)算法是典型最短路径算法,用于计算一个节点到其他节点的最短路径. 它的主要特点是以起始点为中心向外层层扩展(广度优先遍历思想),直到扩展到终点为止 贪心算法(Greedy ...

  4. 图论最短路径算法总结(Bellman-Ford + SPFA + DAGSP + Dijkstra + Floyd-Warshall)

    这里感谢百度文库,百度百科,维基百科,还有算法导论的作者以及他的小伙伴们...... 最短路是现实生活中很常见的一个问题,之前练习了很多BFS的题目,BFS可以暴力解决很多最短路的问题,但是他有一定的 ...

  5. 经典算法题每日演练——第十七题 Dijkstra算法

    原文:经典算法题每日演练--第十七题 Dijkstra算法 或许在生活中,经常会碰到针对某一个问题,在众多的限制条件下,如何去寻找一个最优解?可能大家想到了很多诸如“线性规划”,“动态规划” 这些经典 ...

  6. 一步一步深入理解Dijkstra算法

    先简单介绍一下最短路径: 最短路径是啥?就是一个带边值的图中从某一个顶点到另外一个顶点的最短路径. 官方定义:对于内网图而言,最短路径是指两顶点之间经过的边上权值之和最小的路径. 并且我们称路径上的第 ...

  7. 最短路经算法简介(Dijkstra算法,A*算法,D*算法)

    据 Drew 所知最短路经算法现在重要的应用有计算机网络路由算法,机器人探路,交通路线导航,人工智能,游戏设计等等.美国火星探测器核心的寻路算法就是采用的D*(D Star)算法. 最短路经计算分静态 ...

  8. 图的最短路径-----------Dijkstra算法详解(TjuOj2870_The Kth City)

    做OJ需要用到搜索最短路径的题,于是整理了一下关于图的搜索算法: 图的搜索大致有三种比较常用的算法: 迪杰斯特拉算法(Dijkstra算法) 弗洛伊德算法(Floyd算法) SPFA算法 Dijkst ...

  9. 图的最短路径---迪杰斯特拉(Dijkstra)算法浅析

    什么是最短路径 在网图和非网图中,最短路径的含义是不一样的.对于非网图没有边上的权值,所谓的最短路径,其实就是指两顶点之间经过的边数最少的路径. 对于网图,最短路径就是指两顶点之间经过的边上权值之和最 ...

随机推荐

  1. 测试中认识 sqlite

    1.SQLite,是一款轻型的数据库:简单, 轻松的API 单词速记中单词离线包也用到sqlite 百度了一下,基本的使用语句: .help .quit sqlite3 testDB.db 在当前目录 ...

  2. 怎么把openrety 里边的 table 优雅的打印出来

    1.安装 loarocks 库以后 2.安装 Penlight 插件 3.如下图所示 4.利用dump 函数优雅的打印 table

  3. not

    x = [] print(x) print(not x) print(x is None) print(not x is None) print(x is not None)

  4. bzoj 4465 游戏中的学问

    Written with StackEdit. Description 大家应该都见过很多人手拉手围着篝火跳舞的场景吧?一般情况下,大家手 拉手跳舞总是会围成一个大圈,每个人的左手拉着旁边朋友的右手, ...

  5. python3 csv数据读入/写出

    这是读入 1 import csv 2 #打开文件,用with打开可以不用去特意关闭file了,python3不支持file()打开文件,只能用open() 3 with open("XXX ...

  6. Cocos2d-x -自己定义动作 圆周运动

    原文地址:http://blog.csdn.net/u012945598/article/details/17605409 在之前的文章中我们以前讲过Cocos2d-x中的各种动作的用法,我们先来简单 ...

  7. Tomcat起了一个测试桩,调用该测试桩无响应

    有时在测试新业务流程时因为涉及多个不同接口的调用,而这些被调用的服务端因为网络权限或开发进度问题暂时对我们不可达,那么我们可以通过模拟接口返回来完成我们新业务的测试.这次碰到的问题是我明明起了该测试桩 ...

  8. php redis 命令合集

    1.https://www.cnblogs.com/aipiaoborensheng/p/5666005.html 2.https://www.cnblogs.com/doanddo/p/734908 ...

  9. HDOJ5876(补图的最短路)

    Sparse Graph Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)To ...

  10. Linux Skills

    ++实现RedHat非正常关机的自动磁盘修复先登录到服务器,然后在/etc/sysconfig里增加一个文件autofsck,内容如下:AUTOFSCK_DEF_CHECK=yesPROMPT=yes ...