前置扯淡

一年多前学的最短路,当时就会了几个名词的拼写,啥也没想过

几个月之前,听说了“全源最短路”这个东西,当时也没说学一下,现在补一下(感觉实在是没啥用)

介绍

由于\(spfa\)容易被卡,实际上我们在\(O(nlog \space n)\) 的算法只有堆优化的\(Dijkstra\)

由于先天问题,\(Dijkstra\)无法处理在负权图上的问题

所以“\(Johnson\)全源最短路”算法就应运而生了

算法流程

我们针对\(Dijkstra\)无法处理负权图进行优化

我们考虑如何把每条边的权值转化成正数

这里引入“势能”的概念

势能需要一个起始点:建立一个虚拟源点(类网络流?),向每一个点连一条权值为\(0\)的有向边

跑一遍\(spfa\),记录每个点到虚拟源点的最短路,记为\(res[]\)

(这里问显然\(dis=0\)的同学,请注意这可能是一个负权图)

然后我们把每一条边的边权操作一下:

e[num].dis+=res[e[num].from]-res[e[num].to];

这里\(e[]\)是前向星式建图

这样我们保证了每条边的权值都是正数(思考易得)

然后我们跑\(n\)次\(Dijkstra\),最后

ans[from][to]-=res[from]-res[to];

复杂度\(O(n^2 \space log \space n)\)(\(spfa\)预处理复杂度忽略)

CODE

link-LGOJ5905 【模板】Johnson全源最短路

#include<bits/stdc++.h>
using namespace std;
#define int long long
namespace yspm{
inline int read()
{
int res=0,f=1; char k;
while(!isdigit(k=getchar())) if(k=='-') f=-1;
while(isdigit(k)) res=res*10+k-'0',k=getchar();
return res*f;
}
const int N=4e3+10;
struct node{int to,dis,nxt;}e[N<<3];
int head[N],n,m,cnt,app[N],res[N],ans,tmp[N]; bool vis[N];
inline void add(int u,int v,int w)
{
e[++cnt].dis=w; e[cnt].nxt=head[u]; e[cnt].to=v;
return head[u]=cnt,void();
}
inline bool spfa(int s)
{
queue<int> q; memset(res,0x3f,sizeof(res));
q.push(s); vis[s]=1; res[s]=0;
while(!q.empty())
{
int fr=q.front(); q.pop(); vis[fr]=0;
for(int i=head[fr];i;i=e[i].nxt)
{
int t=e[i].to,dist=e[i].dis+res[fr];
if(res[t]>dist)
{
res[t]=dist;
if(!vis[t])
{
if(++app[t]>=n) return 0;
vis[t]=1; q.push(t);
}
}
}
}
return 1;
}
#define mp make_pair
inline void dij(int s)
{
priority_queue<pair<int,int> > q;
q.push(mp(0,s)); memset(vis,0,sizeof(vis));
for(int i=1;i<=n;++i) tmp[i]=1e9; tmp[s]=0; ans=0;
while(!q.empty())
{
int fr=q.top().second; q.pop();
if(vis[fr]) continue; vis[fr]=1;
for(int i=head[fr];i;i=e[i].nxt)
{
int t=e[i].to,dist=e[i].dis+tmp[fr];
if(tmp[t]>dist)
{
tmp[t]=dist;
if(!vis[t]) q.push(mp(-dist,t));
}
}
}
for(int i=1;i<=n;++i)
{
if(tmp[i]==1e9) ans+=tmp[i]*i;
else ans+=i*(tmp[i]+res[i]-res[s]);
}
return printf("%lld\n",ans),void();
}
signed main()
{
n=read(); m=read(); for(int i=1,u,v,w;i<=m;++i) u=read(),v=read(),w=read(),add(u,v,w);
for(int i=1;i<=n;++i) add(n+1,i,0); if(!spfa(n+1)) return puts("-1"),0;
for(int i=1;i<=n;++i) for(int j=head[i];j;j=e[j].nxt) e[j].dis+=res[i]-res[e[j].to];
for(int i=1;i<=n;++i) dij(i);
return 0;
}
}
signed main(){return yspm::main();}

应用前景

这个破玩意学它有什么用呢?

求解最小费用最大流就是不断求解最短路,然后通过最短路增广的过程

由于走反向边费用要取负,无法使用 \(Dijkstra\) 增广,只能通过 \(Bellman\text{-}Ford\)

而有了 \(Johnson\) 算法以后,就可以先做一轮 \(Bellman\text{-}Ford\),

然后不断通过 \(Dijkstra\) 增广,运行更稳定,效率更高

(死了但是老是诈尸的 \(SPFA\) 能少用一点是一点,虽然我没有在网络流实战中使用过这个算法)

【学习笔记】 Johnson 全源最短路的更多相关文章

  1. Johnson全源最短路

    例题:P5905 [模板]Johnson 全源最短路 首先考虑求全源最短路的几种方法: Floyd:时间复杂度\(O(n^3)\),可以处理负权边,但不能处理负环,而且速度很慢. Bellman-Fo ...

  2. Johnson 全源最短路

    学这个是为了支持在带负权值的图上跑 Dijkstra. 为了这个我们要考虑把负的权值搞正. 那么先把我们先人已经得到的结论摆出来.我们考虑先用 SPFA 对着一个满足三角形不等式的图跑一次最短路,具体 ...

  3. Johnson 全源最短路径算法学习笔记

    Johnson 全源最短路径算法学习笔记 如果你希望得到带互动的极简文字体验,请点这里 我们来学习johnson Johnson 算法是一种在边加权有向图中找到所有顶点对之间最短路径的方法.它允许一些 ...

  4. Johnson 全源最短路径算法

    解决单源最短路径问题(Single Source Shortest Paths Problem)的算法包括: Dijkstra 单源最短路径算法:时间复杂度为 O(E + VlogV),要求权值非负: ...

  5. memcached学习笔记——存储命令源码分析下篇

    上一篇回顾:<memcached学习笔记——存储命令源码分析上篇>通过分析memcached的存储命令源码的过程,了解了memcached如何解析文本命令和mencached的内存管理机制 ...

  6. memcached学习笔记——存储命令源码分析上篇

    原创文章,转载请标明,谢谢. 上一篇分析过memcached的连接模型,了解memcached是如何高效处理客户端连接,这一篇分析memcached源码中的process_update_command ...

  7. 模板C++ 03图论算法 2最短路之全源最短路(Floyd)

    3.2最短路之全源最短路(Floyd) 这个算法用于求所有点对的最短距离.比调用n次SPFA的优点在于代码简单,时间复杂度为O(n^3).[无法计算含有负环的图] 依次扫描每一点(k),并以该点作为中 ...

  8. Laravel学习笔记之Session源码解析(上)

    说明:本文主要通过学习Laravel的session源码学习Laravel是如何设计session的,将自己的学习心得分享出来,希望对别人有所帮助.Laravel在web middleware中定义了 ...

  9. Hadoop学习笔记(10) ——搭建源码学习环境

    Hadoop学习笔记(10) ——搭建源码学习环境 上一章中,我们对整个hadoop的目录及源码目录有了一个初步的了解,接下来计划深入学习一下这头神象作品了.但是看代码用什么,难不成gedit?,单步 ...

随机推荐

  1. POJ 1129:Channel Allocation 四色定理+暴力搜索

    Channel Allocation Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13357   Accepted: 68 ...

  2. 18 12 26 css 学习 选择器

    1.标签选择器 标签选择器,此种选择器影响范围大,建议尽量应用在层级选择器中.举例: *{margin:0;padding:0} div{color:red} <div>....</ ...

  3. 第一个eclipse maven项目!我超全!

    前言:以前一直用idea做东西,今天突然想试一下,没想到配置起来是真的麻烦!!!!会出现各种各样的问题,太晚了,本文只做出几处非常严重的问题,如有疑问,请私信,留言 准备:本文     JDK 1.8 ...

  4. adaboost 基于错误提升分类器

    引自(机器学习实战) 简单概念 Adaboost是一种弱学习算法到强学习算法,这里的弱和强学习算法,指的当然都是分类器,首先我们需要简单介绍几个概念. 1:弱学习器:在二分情况下弱分类器的错误率会低于 ...

  5. nodejs(8) 使用ejs渲染动态页面

    使用ejs渲染动态页面 步骤: 安装 ejs 模板引擎npm i ejs -S 使用 app.set() 配置默认的模板引擎 app.set('view engine', 'ejs') 使用 app. ...

  6. 吴裕雄--天生自然MySQL学习笔记:MySQL DELETE 语句

    可以使用 SQL 的 DELETE FROM 命令来删除 MySQL 数据表中的记录. 可以在 mysql> 命令提示符或 PHP 脚本中执行该命令. 语法 以下是 SQL DELETE 语句从 ...

  7. 201771010123汪慧和《面向对象程序设计JAVA》第八周实验总结

    一.理论部分 1.接口 用interface声明,是抽象方法和常量值定义的集 合.从本质上讲,接口是一种特殊的抽象类. 在Java程序设计语言中,接口不是类,而是对类 的一组需求描述,由常量和一组抽象 ...

  8. c语言的各种技巧

    一.参考网址 1.参考网址1:C 语言的奇技淫巧 二.

  9. Kafka学习(学习过程记录)

    Apache kafka 这,仅是我学习过程中记录的笔记.确定了一个待研究的主题,对这个主题进行全方面的剖析.笔记是用来方便我回顾与学习的,欢迎大家与我进行交流沟通,共同成长.不止是技术. Kafka ...

  10. jquery时钟

    <script type="text/javascript"> function getDate(){ var mydate = new Date(); //时间对象 ...