Primal_Dual 原始对偶
不是费用流都需要用 SPFA 吗。
众所周知,SPFA 去世了,然后网络流显然有负边。于是我们可以像 Johnson 全源最短路一样,给边加上势能,具体实现看我之前的 博客 啦。
然后对于每一次跑 Dijkstra ,然后得到最短路,把势能要再加上这个最短路,可以证明这样操作一次图上不会再有负边。
也正因如此我们不能用 \(dinic\) ,我们不保证在走了多条增广路后仍然边权非负,所以我们可以记录最短路的路径,然后每次增广一条,这样就能保证正确。这个似乎是 KM算法吗?反正都是增广一条,没有学过KM,所以不敢下定论。
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 int N=5e3+3;
const int INF=0x3f3f3f3f;
int n,m,S,T;
struct Edge{
int v,w,c;
};
vector<int>head,nxt;
vector<Edge>to;
inline void join(int u,int v,int w,int c){
nxt.push_back(head[u]);
head[u]=to.size();
to.push_back({v,w,c});
}
queue<int>Q;
int h[N];
bool inq[N];
inline void spfa(){
for(int i=1;i<=n;++i) h[i]=INF,inq[i]=0;
h[S]=0;Q.push(S);inq[S]=1;h[S]=0;
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,c=to[i].c,w=to[i].w;
if(w and h[v]>h[u]+c){
h[v]=h[u]+c;
if(!inq[v]){
inq[v]=1;
Q.push(v);
}
}
}
}
}
int dis[N];
struct node{
int d,x;
inline friend bool operator <(node x,node y){
return x.d<y.d;
}
};
int cur[N];bool vis[N];
struct way{
int v,id;
}e[N];
priority_queue<node>q;
inline bool dijkstra(){
while(!q.empty() ) q.pop();
for(int i=1;i<=n;++i) dis[i]=INF,vis[i]=0;
dis[S]=0;q.push({0,S});
while(!q.empty() ){
int u=q.top().x;q.pop();
if(vis[u]) continue;vis[u]=1;
for(int i=head[u];~i;i=nxt[i]){
int v=to[i].v,w=to[i].w,c=to[i].c+h[u]-h[v];
if(w and dis[v]>dis[u]+c){
e[v].v=u;
e[v].id=i;
dis[v]=dis[u]+c;
if(!vis[v]){
q.push({-dis[v],v});
}
}
}
}
return dis[T]!=INF;
}
int minc,maxf;
inline void PD(){
while(dijkstra() ){
for(int i=S;i<=T;++i) h[i]+=dis[i];
ll minf=INF;
for(int i=T;i!=S;i=e[i].v){
minf=min(minf,to[e[i].id].w);
}
for(int i=T;i!=S;i=e[i].v){
to[e[i].id].w-=minf;
to[e[i].id^1].w+=minf;
minc+=minf*to[e[i].id].c;
}
maxf+=minf;
}
}
int main(){
//file(a);
//freopen("a.in","r",stdin);
n=read();m=read();S=read();T=read();
head.resize(n+1,-1);
for(int i=1;i<=m;++i){
int u=read(),v=read(),w=read(),c=read();
join(u,v,w,c);join(v,u,0,-c);
}
spfa();
PD();
printf("%d %d\n",maxf,minc);
return 0;
}
Primal_Dual 原始对偶的更多相关文章
- 费用流 Dijkstra 原始对偶方法(primal-dual method)
简单叙述用Dijkstra求费用流 Dijkstra不能求有负权边的最短路. 类似于Johnson算法,我们也可以设计一个势函数,以满足在与原图等价的新图中的边权非负. 但是这个算法并不能处理有负圈的 ...
- Superpixel Based RGB-D Image Segmentation Using Markov Random Field——阅读笔记
1.基本信息 题目:使用马尔科夫场实现基于超像素的RGB-D图像分割: 作者所属:Ferdowsi University of Mashhad(Iron) 发表:2015 International ...
- [转]从入门到精通: 最小费用流的“zkw算法”
>>>> 原文地址:最小费用流的“zkw算法” <<<< 1. 网络流的一些基本概念 很多同学建立过网络流模型做题目, 也学过了各种算法, 但是对于基本 ...
- 详解zkw算法解决最小费用流问题
网络流的一些基本概念 很多同学建立过网络流模型做题目, 也学过了各种算法, 但是对于基本的概念反而说不清楚. 虽然不同的模型在具体叫法上可能不相同, 但是不同叫法对应的思想是一致的. 下面的讨论力求规 ...
- 网络流板子/费用流板子 2018南京I题+2016青岛G题
2018南京I题: dinic,链式前向星,数组队列,当前弧优化,不memset全部数组,抛弃满流点,bfs只找一条增广路,每次多路增广 #include <bits/stdc++.h> ...
- Luogu P3381 (模板题) 最小费用最大流
<题目链接> 题目大意: 给定一张图,给定条边的容量和单位流量费用,并且给定源点和汇点.问你从源点到汇点的最带流和在流量最大的情况下的最小费用. 解题分析: 最小费用最大流果题. 下面的是 ...
- 省队集训 Day3 吴清华
[题目大意] 给网格图,共有$n * n$个关键节点,横向.纵向距离均为$d$,那么网格总长度和宽度均为$(n+1) * d + 1$,最外围一圈除了四角是终止节点.要求每个关键节点都要通过线连向终止 ...
- 【P2405】方格取数问题加强版(费用流)
考虑如何建图.还是老样子先拆点,然后把每两个点之间连接两条边,一条流量为1,费用为-点权,处理是否走这个点.一条流量无限,没有费用,因为哪怕一个点选过了,它的地方还是可以重复走过去的. 然后把经由一个 ...
- Andrew Ng机器学习笔记+Weka相关算法实现(五)SVM最优间隔和核方法
这一章主要解说Ng的机器学习中SVM的兴许内容.主要包括最优间隔分类器求解.核方法. 最优间隔分类器的求解 利用以一篇讲过的的原始对偶问题求解的思路,我们能够将相似思路运用到SVM的求解上来. 详细的 ...
随机推荐
- mpvue打包没有app.json等配置文件的解决方法
问题 一早上折腾了1个小时,小程序始终提示查找不到'app.json'文件.mpvue重新打包,光生成内容文件无配置文件. 解决办法 出错原因:版本问题 只需要把packpage.json里的mpvu ...
- java中throws子句是怎么用的?工作原理是什么
7.throws子句 马克-to-win:当你的方法里抛出了checked异常,如你不catch,代表你当时不处理(不想处理或没条件处理),但你必须得通过"throws那个异常"告 ...
- 每日学习+AS小相册+导入图片标红的原因
学习内容: 1.TextView(怎么设置文本). Button(怎么设置按钮事件). ImageView(怎么设置图片) 2.LinearLayout的基本使用 今日成果:做了一个小相册 遇到的问题 ...
- jboss 7.1.1.final 报错 set the maxParameterCount attribute on the Connector
Therefore, I cannot just add the connector attribute in standalone.xml like so: 在 <JBOSS_HOME> ...
- 初识react中高阶组件
高阶组件并不是一个组件,而是一个函数 这个函数返回值是一个组件,并且接受一个组件做为参数:并且返回一个新组件: function HighOC(WrapComponent){ //定义一个高阶组件 , ...
- Mybatis插入数据
对上文->Mybatis快速入门-<进行代码修改 1.在UserMapper.xml中添加插入操作 <!-- 插入操作--> <insert id="save& ...
- SQLite 数据库使用记录
SQLite 数据库使用记录 官网 https://www.sqlite.org/index.html 下载地址 https://www.sqlite.org/download.html 参考资料 S ...
- Warmup小记
什么是warmup 热身,在刚刚开始训练时以很小的学习率进行训练,使得网络熟悉数据,随着训练的进行学习率慢慢变大,到了一定程度,以设置的初始学习率进行训练,接着过了一些inter后,学习率再慢慢变小: ...
- Mysql学习day1
安装了Mysql以及SQLyog,将SQLyog和数据库做了连接. 学习了基础数据类型以及命令行语句 1 alter table `student` rename as `stu``lesson` 2 ...
- 记一次mysql请求超时甩锅历程
今天下午业务找我说是线上环境一个mysql库很慢,请求出现了大量的超时,让帮忙看看,以下为查找过程及甩锅过程. 1. mysql请求超时,ok,我们所有线上mysql都是开启了慢查询日志的,查找慢查询 ...