一种最短路求法(个人觉得比DIJKSTRA好用)

用于有向图。

大概思路:从根节点开始,枚举每一个点,同时更新他们所联通的点的最短路径,如果路径被更新,则把这个点入队,一直重复这个操作直到队伍为空为止。  

代码:

struct edge {
int next, to, v;
}e[];//存图,next代表同一个头结点的下一条边 void spfa(int S) {
int p, x, y, l, r;
for (x = ; x <= n; ++x)
dis[x] = inf;
q[] = S, dis[S] = , v[S] = ;//初始化
for (l = r = ; l != (r + ) % N; ) {
p = q[l], ++l %= N;//每次取出队首
for (x = first[p]; x; x = e[x].next)//遍历与队首同头的每一条边
if (dis[p] + e[x].v < dis[(y = e[x].to)]) {//如果可以更新
dis[y] = dis[p] + e[x].v;//更新
if (!v[y]) {
v[y] = ;
q[++r %= N] = y;//入队
}
}
v[p] = ;
}
}

但是这种做法容易被卡掉(神奇奶牛),所以可以采用SLF优化。

SLF优化:每一次都把即将入队的值与队首值比较,若比队首值小,则存入队首。

为什么呢?

因为每一次都会从队首开始遍历,当队首是最小值时,被更新的所以节点的值也会是最小值,这样可以节省很大一部分时间。

(有点抽象。。举个例子吧)

(我不想画图)

这里需要注意:只有dis[]存储路径值,q[]存储的是当前最小路径值所在的位置,包括edge里的next也是同一个起点的上一对点的序号。(这里的头就是First[]的下标)

这里各种各样的序号很多。。特别容易弄混。会把各种序号分段输出的程序放在结尾,看不懂的话试几组样例看看输出会很有帮助。

到这里只是第一次更新。

下面是第二次更新:

接下来就可以以此类推了。。如果看不懂的话下面是分段输出的代码,结合上面的图看,体会一下中心思想。

代码

#include<iostream>
using namespace std;
struct edge {
int next, to, v;
edge(){}
edge(int x,int y,int z)
{
next=x;
to=y;
v=z;
}
}e[]; int first[];
int tot;
int dis[];
int q[];
int v[];
void add_edge(int x, int y,int z) {
e[++tot] = edge(first[x], y,z);
first[x] = tot;
}
int n;
int N=; int inc(int x) {
x = x + ;
x = x % N;
return x;
} int dec(int x) {
x = x - + N;
x = x % N;
return x;
} void spfa(int S) {
int p, x, y, l, r;
for (x = ; x <= n; ++x)
dis[x] = 0x7ffff;
q[] = S, dis[S] = , v[S] = ;
for (l = r = ; l != (r + ) % N; ) {
p = q[l];
cout<<"从第"<<p<<"号边开始遍历"<<endl;
l=inc(l);
for (x = first[p]; x; x = e[x].next)
{
cout<<"这时是第"<<x<<"号边"<<endl;
if (dis[p] + e[x].v < dis[(y = e[x].to)]) {
cout<<"更新"<<" "<<"将"<<dis[y];
dis[y] = dis[p] + e[x].v;
cout<<"更新为"<<dis[y]<<endl;
if (!v[y]) {
v[y] = ;
if (dis[y] < dis[q[l]])
{q[(l=dec(l))] = y;
cout<<"从队首插入"<<y<<endl;
cout<<"这时l为"<<l<<"r不变"<<endl;
}
else
{q[(r=inc(r))] = y;
cout<<"从队尾插入"<<y<<endl;
cout<<"这时l不变r变为"<<r<<endl; }
cout<<"更新后的队列为"<<endl;
for(int i=;i<=n;i++)
{
cout<<q[i]<<" ";
} cout<<endl;
cout<<"入队情况为"<<endl;
for(int i=;i<=n;i++)
cout<<"第"<<i<<"号元素"<<v[i]<<" ";
cout<<endl;
}
}
}
v[p] = ;
cout<<"此时最短路径被更新为"<<endl;
for(int i=;i<=n;i++)
{
cout<<dis[i]<<" ";
}
cout<<endl;
}
} int main()
{
int m,S;
cin>>n>>m>>S;
int x,y,z;
for(int i=;i<=m;i++)
{
cin>>x>>y>>z;
add_edge(x,y,z);
} spfa(S);
cout<<"最终最短路径"<<endl;
for(int i=;i<=n;i++)
{
cout<<dis[i]<<" ";
} cout<<"一共有"<<tot<<"个节点,分别是"<<endl;
for(int i=;i<=tot;i++)
{
cout<<"与它同起点的上一对点为"<<e[i].next<<"号"<<" "<<"它指向"<<e[i].to<<"这个点"<<endl;
}
cout<<"下面输出First数组"<<endl;
for(int i=;i<=tot;i++)
{
cout<<first[i]<<" ";
} }

这是举例用的样例:

4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
到这里就结束啦!希望可以看懂!
蒟蒻的第二篇博客(再放个烟花吧!)

【模板】SPFA(不完全详解)的更多相关文章

  1. 高性能JavaScript模板引擎实现原理详解

    这篇文章主要介绍了JavaScript模板引擎实现原理详解,本文着重讲解artTemplate模板的实现原理,它采用预编译方式让性能有了质的飞跃,是其它知名模板引擎的25.32 倍,需要的朋友可以参考 ...

  2. OpenCV模板匹配函数matchTemplate详解

    参考文档:http://www.opencv.org.cn/opencvdoc/2.3.2/html/doc/tutorials/imgproc/histograms/template_matchin ...

  3. Javascript模板引擎mustache.js详解

    mustache.js是一个简单强大的Javascript模板引擎,使用它可以简化在js代码中的html编写,压缩后只有9KB,非常值得在项目中使用.本文总结它的使用方法和一些使用心得,内容不算很高深 ...

  4. *ecshop 模板中foreach用法详解

    1.foreach分以下几个参数 from, item, name, iteration, index 2.使用foreach循环      如果php要传递一个数组(如:$array)给ecshop ...

  5. ThinkPHP模板IF标签用法详解

    投稿:shichen2014 字体:[增加 减小] 类型:转载 时间:2014-07-01 我要评论 这篇文章主要介绍了ThinkPHP模板IF标签用法,需要的朋友可以参考下 ThinkPHP的IF标 ...

  6. Python时间获取详解,Django获取时间详解,模板中获取时间详解(navie时间和aware时间)

    1.Python获取到的时间 import pytz from datetime import datetime now = datetime.now() # 这个时间为navie时间(自己不知道自己 ...

  7. Ecshop模板中html_options用法详解

    程序部分 <?php $smarty->assign('status_list', $_LANG['cs']); // 订单状态 $smarty->display("ind ...

  8. 【Python-Django】Jinja2模板引擎配置教程详解!!!!

    Jinjia2的官方文档:http://jinja.pocoo.org/docs/2.10/ 1. 安装Jinja2扩展包 $ pip install Jinja2 2. 配置Jinja2模板引擎 T ...

  9. Bellman-ford算法与SPFA算法思想详解及判负权环(负权回路)

    我们先看一下负权环为什么这么特殊:在一个图中,只要一个多边结构不是负权环,那么重复经过此结构时就会导致代价不断增大.在多边结构中唯有负权环会导致重复经过时代价不断减小,故在一些最短路径算法中可能会凭借 ...

  10. 帝国CMS模板$GLOBALS[navclassid]用法详解

    帝国CMS模板程序扩展变量说明:通过这些变量可实现各种更复杂的显示格式. 一.列表/封面模板变量说明:(栏目页或专题页中使用) (一).当前栏目ID或专题ID:$GLOBALS[navclassid] ...

随机推荐

  1. vue整合adminLTE

    前端框架AdminLTE 中文教程 如何用vue整合adminlte模板 1.adminlte 下载地址 : https://github.com/almasaeed2010/AdminLTE/rel ...

  2. [笔记]nginx配置反向代理和负载均衡

    1.nginx配置文件:源码安装情况下,nginx.conf在解压后的安装包内.yum安装,一般情况下,一部分在/etc/nginx/nginx.conf中,一部分在/etc/nginx/conf.d ...

  3. Gitlab启动、停止、重启(两种启动方式)

    因为Gitlab不是我部署的,是之前总监部署的,服务器突然更新系统了,Git服务器就没有自启··自启··自启······,自己操作启动没有成功,然后网上搜了一下都是这三种启动关闭重启的方式,可是我这里 ...

  4. Centos安装JIRA 7.13版本(自己在官方下载最新版)以及破解

    后半部分流程来自:https://www.cnblogs.com/kaola8023/p/6950481.html 安装准备(切记将许可证号备份) 1.准备mysql需要5.6以及以上的版本(注意:建 ...

  5. flask 第六篇 flask内置的session

    Flask中的Session非常的奇怪,他会将你的SessionID存放在客户端的Cookie中,使用起来也非常的奇怪 1. Flask 中 session 是需要 secret_key 的 from ...

  6. HailStone序列

    目前HailStone序列还未被证明是否有穷,所以它未必是一个算法. * HailStone序列* n=1时,返回1:* n>1时且为偶数时,{n} ∪ {n/2}* n>1时且为奇数时, ...

  7. ArrayList && HashMap扩容策略

    ArrayList扩容策略:默认10 扩容时是base + base/2, 即10 15 22 33 49...扩容时不安全:grow方法扩容时,赋值 elementData = Arrays.cop ...

  8. 最长公共子子串 java

    package maxCommon; /** * 找到最长公共子串 * @author root */ public class MaxCommonUnSeries { public static v ...

  9. vue 如何修改element.style样式

    在css样式表里面加入一个背景样式background:#FFFFFF ! important

  10. 阶段3 3.SpringMVC·_02.参数绑定及自定义类型转换_4 请求参数绑定集合类型

    jabaBean里面有集合的情况 把account里面的user对象先注释掉.get和set都注释掉.然后toString方法需要重写 List和Map这两种对象.生成get和set方法 toStri ...