SPFA和DIJ求最短路的算法的坑点一直是很多的。经常会让人搞不懂。

易错案例:

用重载运算符来排序,如:

struct cmp {
bool operator ()(int x, int y)
const
{
return dis[x]>dis[y];
}
};

这种做法是不对的,该dis值在堆里不会更新甚至会堵住。

正确案例:

目前只有两种优化算法最可靠,分别为优先队列来优化spfa或dij。

\(SPFA\):

每次从堆中只需要取出到t的最短路最小的元素进行松弛,这样便可以大大缩小松弛的次数,效率从而得到提高。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <queue>
#define int long long
using namespace std;
int n, m, s, a, b, vis[1000100], dis[1000100], cnt, lin[1000100];
struct cym {
int from, to, len, nex;
}e[2000100];
struct cmp{
bool operator () (int x, int y)
{
return dis[x] > dis[y];
}
};
inline void add(int u, int v, int l)
{
e[++cnt].from = u;
e[cnt].to = v;
e[cnt].len = l;
e[cnt].nex = lin[u];
lin[u] = cnt;
}
priority_queue <int, vector <int>, cmp> q;
signed main()
{
scanf("%lld%lld%lld", &n, &m, &s);
for (int i = 1; i <= n; i++)
dis[i] = 2147483647;
for (int i = 1; i <= m; i++)
{
int a, b, c;
scanf("%lld%lld%lld", &a, &b, &c);
add(a, b, c);
}
dis[s] = 0;
q.push(s);
// printf("%d\n", lin[s]);
while(!q.empty())
{
int cur = q.top();
q.pop();
vis[cur] = 0;
for (int i = lin[cur]; i; i = e[i].nex)
{
if (dis[e[i].to] > dis[cur] + e[i].len)
{
dis[e[i].to] = dis[cur] + e[i].len;
if (!vis[e[i].to])
{
q.push(e[i].to);
vis[e[i].to] = 1;
}
}
}
}
for (int i = 1; i <= n; i++)
printf("%lld ", dis[i]);
}

\(DIJ\):

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
int n, m, s, lin[100010], cnt, a, b, c, vis[100010];
struct cym {
int d, num; }dis[100100];
struct edge {
int to, len, nex;
}e[200010];
inline void add(int f, int t, int l)
{
e[++cnt].len = l; e[cnt].to = t; e[cnt].nex = lin[f]; lin[f] = cnt;
}
bool operator < (cym a, cym b)
{
return a.d > b.d;
}
priority_queue <cym> q;
int main()
{
scanf("%d%d%d", &n, &m, &s);
for (int i = 1; i <= m; i++)
{
scanf("%d%d%d", &a, &b, &c);
add(a, b, c);
}
for (int i = 1; i <= n; i++)
dis[i].d = 2147483647, dis[i].num = i;
dis[s].d = 0;
q.push(dis[s]);
while(!q.empty())
{
cym cur = q.top(); q.pop();
if (vis[cur.num])
continue;
vis[cur.num] = 1;
for (int i = lin[cur.num]; i; i = e[i].nex)
if (cur.d + e[i].len < dis[e[i].to].d && !vis[e[i].to])
dis[e[i].to].d = e[i].len + cur.d, q.push(dis[e[i].to]);
}
for (int i = 1; i <= n; i++)
printf("%d ", dis[i].d);
}

DIJ的优化,和spfa的优化的更多相关文章

  1. spfa + slf优化

    最近在练习费用流 , 不是要用spfa吗 ,我们教练说:ns学生写朴素的spfa说出去都让人笑 . QwQ,所以就去学了一下优化 . slf优化就是双向队列优化一下,本来想用lll优化,可是优化后我t ...

  2. SPFA 小优化*2

    /* bzoj 2763 SPFA小优化 循环队列+SLF 顺面改掉自己之前手打qeueu的坏毛病*/ #include<iostream> #include<cstring> ...

  3. HDU 1535 Invitation Cards(SPFA,及其优化)

    题意: 有编号1-P的站点, 有Q条公交车路线,公交车路线只从一个起点站直接到达终点站,是单向的,每条路线有它自己的车费. 有P个人早上从1出发,他们要到达每一个公交站点, 然后到了晚上再返回点1. ...

  4. POJ 3013 Big Christmas Tree(最短Dijkstra+优先级队列优化,SPFA)

    POJ 3013 Big Christmas Tree(最短路Dijkstra+优先队列优化,SPFA) ACM 题目地址:POJ 3013 题意:  圣诞树是由n个节点和e个边构成的,点编号1-n. ...

  5. [BZOJ 2200][Usaco2011 Jan]道路和航线 spfa+SLF优化

    Description Farmer John正在一个新的销售区域对他的牛奶销售方案进行调查.他想把牛奶送到T个城镇 (1 <= T <= 25,000),编号为1T.这些城镇之间通过R条 ...

  6. 【最短路径】 SPFA算法优化

    首先先明确一个问题,SPFA是什么?(不会看什么看,一边学去,传送门),SPFA是bellman-ford的队列优化版本,只有在国内才流行SPFA这个名字,大多数人就只知道SPFA就是一个顶尖的高效算 ...

  7. 队列优化dijsktra(SPFA)的玄学优化

    转载:大佬博客 最近想到了许多优化spfa的方法,这里想写个日报与大家探讨下 前置知识:spfa(不带任何优化) 由于使用较多 STLSTL ,本文中所有代码的评测均开启 O_2O2​ 优化 对一些数 ...

  8. SPFA队列优化

    spfa队列优化(用来求最短路) 实现方法: 1.存入图.可以使用链式前向星或者vocter. 2.开一个队列,先将开始的节点放入. 3.每次从队列中取出一个节点X,遍历与X相通的Y节点,查询比对   ...

  9. SPFA的优化

    [为什么要优化] 关于SPFA,他死了(懂的都懂)   进入正题... 一般来说,我们有三种优化方法. SLF优化: SLF优化,即 Small Label First  策略,使用 双端队列 进行优 ...

  10. [MySQL性能优化系列]LIMIT语句优化

    1. 背景 假设有如下SQL语句: SELECT * FROM table1 LIMIT offset, rows 这是一条典型的LIMIT语句,常见的使用场景是,某些查询返回的内容特别多,而客户端处 ...

随机推荐

  1. @PostConstruct使用总结

    https://blog.csdn.net/qq_37636695/article/details/84791468 https://www.jianshu.com/p/aba99a49a459 @P ...

  2. springMvc之常用注解介绍

    @requestbody和@requestparam的用法  获取请求参数的方法 get请求: 直接获取request    如: public String getHtml(HttpServletR ...

  3. java之struts2之拦截器

    1.struts2能完成数据的设置,数据的封装,数据的类型转换,数据的校验等等.struts2是如何来完成这些功能的?struts2的所有功能都是由拦截器来完成的. 2.拦截器是struts2的核心. ...

  4. C# 使用代理实现方法过滤

    一.为什么要进行方法过滤 一些情况下我们需要再方法调用前记录方法的调用时间和使用的参数,再调用后需要记录方法的结束时间和返回结果,当方法出现异常的时候,需要记录异常的堆栈和原因,这些都是与业务无关的代 ...

  5. openssl jia adress

    ???????????????????????????????????????????openssl证IP 首先创建openssl.cnf, 内容如下. 其中organizationalUnitNam ...

  6. 主机与虚拟机ping不通问题

    在win10 上利用vm安装linux虚拟机,物理机与虚拟机之间不能ping通,除了检查物理机与虚拟机防火墙状态外,还要注意物理机设置的ip与虚拟机设置的ip,要在同一个ip段

  7. 1.1 文档PUT内部原理

    文档更新原理:       PUT 一条数据的时候,如果是全量替换,ES并不会覆盖原来的文档,而是新创建一个文档,并将version+1,原文档标记为deleted,不会立刻物理删除.ES会在集群的d ...

  8. Eclipse开发环境(一):下载和安装

    一.Eclipse下载及安装 1. 下载 进入官网https://www.eclipse.org/,点击 IDE & Tools 选择Java EE 选择Luna Packages 选择Win ...

  9. 在angular 8中使用 less

    在angular 6中使用 less 新项目 ng new [appname] --style less 已有的项目 修改 *.css 文件及引用处后缀名为 less并在 angular.json 文 ...

  10. 如何在vue项目中引入element-ui

    安装 elementUI npm install element-ui --save 引入elementUI import ElementUI from 'element-ui' import 'el ...