luogu3381【模板】最小费用最大流(zkw费用流板子)
来源:互联网 发布:外交部流氓回答知乎 编辑:程序博客网 时间:2024/06/13 21:21
%%%xtx的代码了好久,又翻了很多文章,终于算是差不多看懂了???
费用流问题,是建立在最大流问题基础之上的,也就是说,现在流要钱了,我们要求出最大流,可能有很多个最大流,我们还要费用最小的那个。比较直观的一个想法便是:把原来的bfs分层变成spfa等最短路算法,求出从s到t费用最小的一条路径来增广。然而这样我们就失去了Dinic的一个优势,即多路增广。因为每次我们进行增广后,最短路都不一定再满足了,我们需要重新运行spfa来算。这样就比较慢。zkw费用流改进在哪里呢?他使用了类似km算法的每次修改顶标的做法。
任何一个最短路算法保证, 算法结束时对任意指向顶点
在最小费用流的计算中, 我们每次沿
Di+cij≥Dj ⇔ Di−Dj+cij≥0 ①
Di+cij=Dj ⇔ Di−Dj+cij=0 ②
对于一个顶标D,我们可以不断的dfs找Di−Dj+cij=0的增广路经
假设我们当前dfs失败
即使失败还是有一些点能满足Di−Dj+cij=0的
这些点被我们当前dfs到了
我们记这些点的点集为
找到
然后我们对
证明:
弧(i,j)可以分成四类,再根据当前dfs失败的条件,有:
i∈V,j∉V 原来Di−Dj+cij≥Δ>0 新图
i∈V,j∈V 原来Di−Dj+cij=0 新图
i∉V,j∉V 原来Di−Dj+cij≥0 新图
i∉V,j∈V 原来Di−Dj+cij≥0 新图
可以发现第一类弧中一定有至少一条满足
原来Di−Dj+cij=Δ 新图
即至少有一条新的边进入了 Dj=Di+cij 的子图。
这样直到找不到这样的
本来我们要记录D数组,每次修改距离标记改的是D数组,但是我们也可以不计这个D数组,每条边(u,v)的c就表示
#include <bits/stdc++.h>using namespace std;#define ll long long#define N 5010#define inf 0x3f3f3f3finline int read(){ int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();} while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return x*f;}int n,m,s,t,h[N],num=1,cost=0,price=0,mxflow=0;bool vis[N];struct edge{ int to,next,w,c;}data[50010<<1];inline void add(int x,int y,int w,int c){ data[++num].to=y;data[num].next=h[x];h[x]=num;data[num].w=w;data[num].c=c; data[++num].to=x;data[num].next=h[y];h[y]=num;data[num].w=0;data[num].c=-c;}inline int dinic(int x,int low){ vis[x]=1;if(x==t){cost+=low*price;mxflow+=low;return low;}int tmp=low; for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(vis[y]||!data[i].w||data[i].c) continue; int res=dinic(y,min(tmp,data[i].w)); tmp-=res;data[i].w-=res;data[i^1].w+=res; if(!tmp) return low; }return low-tmp;}inline bool label(){ int d=inf; for(int x=1;x<=n;++x){ if(!vis[x]) continue; for(int i=h[x];i;i=data[i].next){ int y=data[i].to;if(vis[y]) continue; if(data[i].w&&data[i].c<d) d=data[i].c; } }if(d==inf) return 0; for(int x=1;x<=n;++x){ if(!vis[x]) continue; for(int i=h[x];i;i=data[i].next) data[i].c-=d,data[i^1].c+=d; }price+=d;return 1;}int main(){// freopen("a.in","r",stdin); n=read();m=read();s=read();t=read(); while(m--){ int x=read(),y=read(),w=read(),c=read();add(x,y,w,c); }do do memset(vis,0,sizeof(vis));while(dinic(s,inf)); while(label()); printf("%d %d\n",mxflow,cost); return 0;}
- luogu3381【模板】最小费用最大流(zkw费用流板子)
- 最小费用最大流/费用流zkw算法模板(洛谷3381)
- 最小费用最大流(板子)
- zkw最小费用流
- 最小费用最大流 zkw算法
- ZKW费用流 模板
- zkw费用流模板
- zkw费用流模板
- ZKW费用流 模板
- HDU 4744 Starloop System(ZKW最小费用最大流)
- 最小费用流---ZKW算法
- 模板[最小费用最大流]
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流模板
- 最小费用最大流,模板
- 最小费用最大流模板
- 最小费用最大流 模板
- 在Windows平台上安装Node.js及NPM模块管理
- Markdown入门操作
- java--集合--Collection--Set
- 传统定时器技术入门-java 类Timer
- sklearn官网学习入门二
- luogu3381【模板】最小费用最大流(zkw费用流板子)
- FZU2278(大数)
- WINDOWS svn 不显示图标状态
- 模仿QQ消息红点拖动效果
- cadence vmanager(九) vplanner介绍
- 554. Brick Wall
- 进程和线程的区别
- leetcode 452. Minimum Number of Arrows to Burst Balloons 消除覆盖区间
- 2、Hibernate的常见配置