学这个是为了支持在带负权值的图上跑 Dijkstra.

为了这个我们要考虑把负的权值搞正。

那么先把我们先人已经得到的结论摆出来。我们考虑先用 SPFA 对着一个满足三角形不等式的图跑一次最短路,具体就是在原图的基础上建立超级源点。

然后我们把得到的这个东西称为 势能 \(h\) ,我们对于原图的每条边 \((u,v)\)的边权加上 \(h_u-h_v\),然后就可以跑 Dijkstra 了,求出的答案是 \(dis_{i,j}-h_i+h_j\).然后我们证明这样搞是对的。

首先需要证明这个搞法不会使求出来的值变化。

对于一条 \(i\) 到 \(j\) 的最短路径,有经过的点集 \(S\) ,那么我们求出的最短路是:

\[dis_{i,j}=(w(S_1,S_2)+h_1-h_2)+(w(S_2,S_3)+h_2-h_3)+...+(w(S_{n-1},S_n)+h_{n-1}+h_n)
\]

然后我们不难发现前后两项有部分可以抵消,所以有(设 \(d_{i,j}\) 为直接 Dijkstra 跑出的答案):

\[dis_{i,j}=(w(S_1,S_2)+h_1-h_2)+(w(S_2,S_3)+h_2-h_3)+...+(w(S_{n-1},S_n)+h_{n-1}+h_n)
\]
\[=d_{i,j}+h_1+h_n
\]

在加上势能满足三角形不等式:\(w(u,v)+h_u \geqslant h_v\)

就是差分约束(和最短路)那个东西啦。然后变形得到所有修改后边权大于0.

就没啦(-)

Johnson 全源最短路

code:

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define file(a) freopen(#a".in","r",stdin),freopen(#a".out","w",stdout)
inline int read(){
int s=0,f=1;char ch=getchar();
while(ch<'0'||'9'<ch) {if(ch=='-') f=-1;ch=getchar();}
while('0'<=ch&&ch<='9') {s=s*10+(ch^48);ch=getchar();}
return s*f;
}
const ll INF=1e18;
const int N=3e3+3;
const int M=6e3+3;
int n,m;
struct Edge{
int v;ll w;
};
vector<int>head,nxt;
vector<Edge>to;
inline void join(int u,int v,int w){
nxt.push_back(head[u]);
head[u]=to.size();
to.push_back({v,w});
}
queue<int>q;
ll h[N];bool inq[N];
int hoop[N];
inline bool SPFA(int s){
while(!q.empty() ) q.pop();
for(int i=1;i<=n+1;++i){
h[i]=INF;inq[i]=0;hoop[i]=0;
}
inq[s]=1;q.push(s);h[s]=0;hoop[s]=1;
while(!q.empty() ){
int u=q.front();q.pop();inq[u]=0;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i].v;ll w=to[i].w;
if(h[v]>h[u]+w){
h[v]=h[u]+w;
if(!inq[v]){
++hoop[v];
if(hoop[v]>n) return false;
q.push(v);
inq[v]=1;
}
}
}
}
return true;
}
ll dis[N][N];int S;
struct node{
int x;
inline friend bool operator <(node x,node y){
return dis[S][x.x]>dis[S][y.x];
}
};
namespace Dijkstra{
priority_queue<node>q;
inline void work(int s){
while(!q.empty() ) q.pop();
for(int i=1;i<=n;++i){
dis[s][i]=INF;
inq[i]=0;
}S=s;
inq[s]=1;q.push({s});dis[s][s]=0;
while(!q.empty() ){
int u=q.top().x;q.pop();inq[u]=0;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i].v;ll w=to[i].w;
if(dis[s][v]>dis[s][u]+w){
dis[s][v]=dis[s][u]+w;
if(!inq[v]){
inq[v]=1;
q.push({v});
}
}
}
}
}
}
struct EDGE{
int u,v,w;
}e[M];
int main(){
//file(a);
n=read();m=read();
head.resize(n+1,-1);
for(int i=1;i<=m;++i){
int u=read(),v=read(),w=read();
join(u,v,w);
e[i]={u,v,w};
}
for(int i=1;i<=n;++i){
join(0,i,0);
}
if(!SPFA(0)) {printf("-1\n");return 0;}
head.clear();
head.resize(n+1,-1);
to.clear();nxt.clear();
for(int i=1;i<=m;++i){
join(e[i].u,e[i].v,e[i].w+h[e[i].u]-h[e[i].v]);
}
for(int i=1;i<=n;++i){
Dijkstra::work(i);
}
for(int i=1;i<=n;++i){
ll ans=0;
for(int j=1;j<=n;++j){
if(dis[i][j]==INF) ans+=1ll*(1e9)*j;
else ans+=1ll*(dis[i][j]-h[i]+h[j])*j;
}
printf("%lld\n",ans);
}
return 0;
}

Johnson 全源最短路的更多相关文章

  1. 【学习笔记】 Johnson 全源最短路

    前置扯淡 一年多前学的最短路,当时就会了几个名词的拼写,啥也没想过 几个月之前,听说了"全源最短路"这个东西,当时也没说学一下,现在补一下(感觉实在是没啥用) 介绍 由于\(spf ...

  2. Johnson全源最短路

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

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

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

  4. Johnson 全源最短路径算法

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

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

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

  6. Johnson算法:多源最短路算法

    Johnson算法 请不要轻易点击标题 一个可以在有负边的图上使用的多源最短路算法 时间复杂度\(O(n \cdot m \cdot log \ m+n \cdot m)\) 空间复杂度\(O(n+m ...

  7. Floyd-Warshall 全源最短路径算法

    Floyd-Warshall 算法采用动态规划方案来解决在一个有向图 G = (V, E) 上每对顶点间的最短路径问题,即全源最短路径问题(All-Pairs Shortest Paths Probl ...

  8. 【算法】单源最短路——Dijkstra

    对于固定起点的最短路算法,我们称之为单源最短路算法.单源最短路算法很多,最常见的就是dijkstra算法. dijkstra主要用的是一种贪心的思想,就是说如果i...s...t...j是最短路,那么 ...

  9. 图论:Floyd-多源最短路、无向图最小环

    在最短路问题中,如果我们面对的是稠密图(十分稠密的那种,比如说全连接图),计算多源最短路的时候,Floyd算法才能充分发挥它的优势,彻彻底底打败SPFA和Dijkstra 在别的最短路问题中都不推荐使 ...

随机推荐

  1. CSS - 定位属性position使用详解(static、relative、fixed、absolute)

    position 属性介绍 (1)position 属性自 CSS2 起就有了,该属性规定元素的定位类型.所有主流浏览器都支持 position 属性. (2)position 的可选值有四个:sta ...

  2. C#编写程序,计算数组中奇数之和和偶数之和

    编写程序,计算数组中奇数之和和偶数之和. 代码: using System; using System.Collections.Generic; using System.Linq; using Sy ...

  3. Android 预置APK

    1.   预置apk,使其不可卸载   第一步:      在 "/vendor/huawei/packages/apps" 目录下创建一个对应名称的文件夹.   第二步:   将 ...

  4. Java中的反射原理以及简单运用(原理+例子)

    @ 目录 学习总结 1. 为什么要使用反射 2. 反射的概念 3. Java反射加载过程 4. 反射优缺点 5. 字节码对象理解 6. 获取字节码对象(.class)的三种方式 7. 反射常用API ...

  5. js,nodejs如何判断文件是什么编码格式

    nodejs编码只支持utf8的编码方式,无论是打开某个文件或者写.js脚本都得以utf8的编码方式保存,不然程序无法运行,读出来的文件是乱码. 如果是在前台,读取文件是通过FileReader或者F ...

  6. three车辆自由转弯(vue 极品飞车)

    //最近没有时间整理代码,就这样吧 <template> <div> <div id="map"></div> </div&g ...

  7. ABP源码分析 - 约定注册(2)

    比较随意,记录下过程,以便忘了以后重拾. 所谓约定注册是指不需要明确写代码注入,只需要按约定规则写服务类,框架自动完成服务注册. 例如,只要这样写,框架就会自动注册. public class Tax ...

  8. OllyDbg---汇编指令

    汇编指令 NOP 无操作 运行这条指令时,不会对寄存器.内存以及堆栈造成任何影响,也就是无操作. 当用一个短指令来替换一个长指令时,如果处理器没有错误,多余的空间将会被NOP填充. 适当数目的NOP指 ...

  9. 帝国CMS网站地图生成插件

    可以生成电脑端也可以生成手机端的地图XML. 安装方法: 这个帝国sitemap插件的安装跟其他插件的安装方式一样,介于可能有人不会安装帝国的插件,就写一下吧,以后你们如果碰到帝国插件也可以参考这个. ...

  10. C# 中托管内存与非托管内存之间的转换

    c#有自己的内存回收机制,所以在c#中我们可以只new,不用关心怎样delete,c#使用gc来清理内存,这部分内存就是managed memory,大部分时候我们工作于c#环境中,都是在使用托管内存 ...