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 ...
随机推荐
- delphi 让子窗体显示最大化
procedure TForm2.FormCreate(Sender: TObject); begin perform(WM_SIZE,SIZE_MAXIMIZED,0); end;
- Delphi WebBrowser内核版本修改D7
private { Private declarations } public { Public declarations } function WriteAppNameToReg:Boolean; ...
- 【JVM之内存与垃圾回收篇】垃圾回收相关算法
垃圾回收相关算法 标记阶段:引用计数算法 在堆里存放着几乎所有的 Java 对象实例,在 GC 执行垃圾回收之前,首先需要区分出内存中哪些是存活对象,哪些是已经死亡的对象.只有被标记为己经死亡的对象, ...
- 【虚拟机】在VMware中为Ubuntu虚拟机设置共享文件夹
[虚拟机]在VMware中为Ubuntu虚拟机设置共享文件夹 零.需求 有些开发工具在Windows上没有,只能在Ubuntu上开发,但是自己电脑是Windows的,开发完成后需要通过Windows分 ...
- DevOps系列——Gitlab私服
Gitlab/GitHub是两兄弟,但GitHub本着共享技术的精神,私有库是要钱滴,而且代码放别人家里,晚上总是有点睡不踏实, 来个代码泄露或者突然被区别对待,比如GitHub断供来自伊朗.叙利亚的 ...
- cnpack导致view快捷键失灵。
学习d10.3.出现怪问题: 卸载cnpack出现: 这下要用快捷键了.那可不烦透了. 如此就ok了. 鸡蛋好吃,还要知道母鸡如何生蛋的?
- hexo搭建博客记录
这是一次hexo搭建博客并引入archer主题的使用记录. 环境准备 首先是hexo工具的安装使用,这个工具是依赖于nodejs的一个命令行工具,并且各种使用也依赖于node生态,所以需要先进行nod ...
- soapUI接口关联教程
1.新建项目结构 步骤如下: 打开soapUI Pro,新建工作空间(点击File-New Workspace) 选中Test右键点击New Project 选中AlloTest右键点击New Tes ...
- 🎀SQL注入拦截工具-动态order by
简介 业务场景经常会存在动态order by 入参情况,在处理动态 order by 参数时,需要防止SQL注入攻击.SQL注入是一种常见的安全漏洞,攻击者可以通过这种手段操纵查询来执行恶意代码. 措 ...
- Java 的 CMS 垃圾回收器和 G1 垃圾回收器在记忆集的维护上有什么不同?
Java 的 CMS 垃圾回收器和 G1 垃圾回收器在记忆集的维护上的不同 记忆集(Remembered Set, RSet)是垃圾回收器用来跟踪跨代引用的重要结构,它记录老年代对象对新生代对象的引用 ...