dij费用流/Johnson Reweighting
dij费用流/Johnson Reweighting
我们一般敲的费用流都是套\(SPFA\)的\(dinic\),这是因为会有负边权,\(dij\)做不了,考虑能不能动点手脚使得我们的边权变成正的
可能会直接想到给每条边+\(INF\),这显然有点难蚌
\(Johnson\ Reweighting\)就是用来解决这个问题的
考虑给每个点赋一个点权\(h[x]\),表示\(S\)走到\(x\)的最短路的长度,我们现在让边\((u,v,w)\)的权变成\(w+h[u]-h[v]\),因为\(h\)是最短距离,所以显然这个值\(\geq 0\),且这样直接跑\(dij\)得到的\(S\)到\(T\)的最短路距离\(v\)加上\(-dis[S]+dis[T]\)就是真正的最短路距离
那么考虑怎么快速得到这个\(h\),显然第一次就直接跑个\(SPFA\),考虑后面怎么办
对于第\(i\)(\(i>1\))次跑\(dij\)时,记\(h_i\)表示跑完第\(i\)次\(dij\)后的最短路
显然我们想用\(h_i\)来操作第\(i\)次\(dij\),但显然这不现实
发现就用\(h_{i-1}\)来操作的话,所有边权也都是非负的,因为对于第\(i-1\)次\(dij\),它会改变的边\((u,v,w)\)满足\(w+h[u]-h[v]=0\)
复杂度是\(O(F(M+NlogN))\),好像\(OI\)里一般常写成\(O(F(N+M)logN)\)
模板(https://www.luogu.com.cn/problem/P3381):
#include<bits/stdc++.h>
using namespace std;
const int N=5e3+5,M=5e4+5,INF=1e9;
int n,m,S,T;
int head[N],cnt=1;
struct node{ int nxt,v,val,w; }tree[M<<1];
void add(int u,int v,int val,int w){
tree[++cnt]={head[u],v,val,w},head[u]=cnt;
tree[++cnt]={head[v],u,0,-w},head[v]=cnt;
}
int dis[N]; bool vis[N];
void spfa(){
for(int i=1;i<=n;++i) dis[i]=INF;
dis[S]=0; queue<int> q; q.push(S);
while(!q.empty()){
int x=q.front(); q.pop(),vis[x]=false;
for(int i=head[x],y;i;i=tree[i].nxt) if(tree[i].val&&dis[y=tree[i].v]>dis[x]+tree[i].w){
dis[y]=dis[x]+tree[i].w;
if(!vis[y]) q.push(y),vis[y]=true;
}
}
}
struct use{
int x,d;
bool operator < (const use &other)const{
return d>other.d;
}
};
int h[N],fr[N],ans,ans1;
bool dij(){
priority_queue<use> q;
for(int i=1;i<=n;++i) dis[i]=INF,vis[i]=false;
q.push({S,dis[S]=0});
while(!q.empty()){
int x=q.top().x; q.pop();
if(vis[x]) continue;
vis[x]=true;
for(int i=head[x],y;i;i=tree[i].nxt) if(tree[i].val&&!vis[y=tree[i].v]){
int t=dis[x]+tree[i].w+h[x]-h[y];
if(t<dis[y]) dis[y]=t,fr[y]=i,q.push({y,dis[y]});
}
}
if(dis[T]==INF) return false;
int mn=INF;
for(int x=T,i=fr[x];x!=S;x=tree[i^1].v,i=fr[x]) mn=min(mn,tree[i].val);
ans+=mn;
for(int x=T,i=fr[x];x!=S;x=tree[i^1].v,i=fr[x]) tree[i].val-=mn,tree[i^1].val+=mn,ans1+=mn*tree[i].w;
for(int i=1;i<=n;++i) if(dis[i]<INF) h[i]+=dis[i];
return true;
}
int main(){
scanf("%d%d%d%d",&n,&m,&S,&T);
for(int i=1,u,v,val,w;i<=m;++i) scanf("%d%d%d%d",&u,&v,&val,&w),add(u,v,val,w);
spfa(); for(int i=1;i<=n;++i) h[i]=dis[i];
while(dij());
printf("%d %d\n",ans,ans1);
return 0;
}
dij费用流/Johnson Reweighting的更多相关文章
- dij 费用流
#include <bits/stdc++.h> using namespace std; typedef long long lld; const int MAXN = 50010, M ...
- HDU 4780 Candy Factory(拆点费用流)
Problem Description A new candy factory opens in pku-town. The factory import M machines to produc ...
- 洛谷P3381 【模板】最小费用最大流(dijstra费用流)
题目描述 如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用. 输入输出格式 输入格式: 第一行包含四个正整数N.M.S.T,分别表 ...
- 费用流 Dijkstra 原始对偶方法(primal-dual method)
简单叙述用Dijkstra求费用流 Dijkstra不能求有负权边的最短路. 类似于Johnson算法,我们也可以设计一个势函数,以满足在与原图等价的新图中的边权非负. 但是这个算法并不能处理有负圈的 ...
- 网络流小记(EK&dinic&当前弧优化&费用流)
欢 迎 来 到 网 络 瘤 的 世 界 什么是网络流? 现在我们有一座水库,周围有n个村庄,每个村庄都需要水,所以会修水管(每个水管都有一定的容量,流过的水量不能超过容量).最终水一定会流向唯一一个废 ...
- 补 第三场多校杭电 费用流 K Subsequence
K Subsequence 这个题目是这个人想吃东西,但是他每次吃的都是他的美味值都必须不递减,可以吃k次,问这个最大的美味值是多少. 这个是一个比较明显的费用流,建图也很好建,但是呢,这个题目卡sp ...
- hdu-5988 Coding Contest(费用流)
题目链接: Coding Contest Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Ot ...
- POJ2195 Going Home[费用流|二分图最大权匹配]
Going Home Time Limit: 1000MS Memory Limit: 65536K Total Submissions: 22088 Accepted: 11155 Desc ...
- BZOJ3130: [Sdoi2013]费用流[最大流 实数二分]
3130: [Sdoi2013]费用流 Time Limit: 10 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 960 Solved: 5 ...
- 洛谷 1004 dp或最大费用流
思路: dp方法: 设dp[i][j][k][l]为两条没有交叉的路径分别走到(i,j)和(k,l)处最大价值. 则转移方程为 dp[i][j][k][l]=max(dp[i-1][j][k-1][l ...
随机推荐
- docker学习 容器的启动过程
这一节我们来稍微了解下docker原理性的东西1 docker run -i -t ubuntu /bin/bash输入上面这行命令,启动一个ubuntu容器时,到底发生了什么?大致过程可以用下 ...
- 万字长文详解SIFT特征提取
本文对 SIFT 算法进行了详细梳理.SIFT即尺度不变特征变换(Scale-Invariant Feature Transform),是一种用于检测和描述图像局部特征的算法.该算法对图像的尺度和旋转 ...
- 什么是 CSS 设计模式
这是转载的,先收藏到我的博客园. 什么是设计模式? 曾有人调侃,设计模式是工程师用于跟别人显摆的,显得高大上:也曾有人这么说,不是设计模式没用,是你还没有到能懂它,会用它的时候. 先来看一下比较官方的 ...
- 【Python】import模块和包
模块和包 一. 模块 Python 模块(Module),是一个 Python 文件,以 .py 结尾,包含了 Python 对象定义和Python语句. 模块能定义函数,类和变量,模块里也能包含可执 ...
- C# 调用 Win10/11 文件关联对话框
方法一:调用未公开接口 IOpenWithLauncher Adobe Acrobat 应该是调用的未公开接口方法 [ComImport] [InterfaceType(ComInterfaceTyp ...
- 基于STM32F4+FREERTOS进行结构体变量的传递
原始参考链接如下↓ Freertos 接收消息队列数据不对,是姿势不正确吗 - STM32H7 - 硬汉嵌入式论坛 - Powered by Discuz! https://www.armbbs.cn ...
- Navicat Premium 16激活教程(NavicatCracker)
1.安装Navicat Premium 16 (注意版本,这里以此版本为例):并下载激活工具 1.1.Navicat Premium 下载路径: http://www.navicat.com.cn/d ...
- 关于全球化大规模混合云 Kubernetes Prometheus 监控体系标准化及 GitOps 自动化改进方案
背景 现状 某司概况: PaaS/SaaS 公司,业务面向全球,包括 东南亚/南亚/中东/欧洲/非洲/美洲/东亚... 生产 k8s 集群数十套,生产非生产 >100 套(多种集群类型,各种公有 ...
- Java 中有哪些垃圾回收算法?
Java 中的垃圾回收算法 Java 中的垃圾回收(Garbage Collection,GC)机制通过多种算法实现对堆内存的管理.以下是常见的垃圾回收算法: 1. 标记-清除算法(Mark-Swee ...
- 如何使用Streamlit快速创建仪表盘?
上文有快速带大家了解streamlit,因为工作需要,这两天尝试构建了仪表盘,也就是咱们常说的Dashboard,本篇文章将教你如何使用 Streamlit 快速创建一个简单的仪表盘. 前言 Stre ...