最大流&最小割&费用流模版
好久都没有搞博客了。想认真写又要准备文化课期末了。
ISAP
- 流程: 原理就是dfs找增广路。
最基础的建反向边以便反悔就不说了。
但是记录一个dep(dis)表示层数,一开始BFS(从t开始,dis[t]=0)处理最小层数,然后再搜索增广路增加限制条件:dis[u]=dis[v]+1,若这样的v找完了,扩大一层u(即dis[u]++),可能会被回溯到前面的某条新路再次搜中。然后特判一下,如果dis[s]>=n即可结束,因为dis[t]永远等于0,dis[s]最大为n-1。
gap(cnt)标记很简单:就是记录每个dis[]值的个数,若某一中间dis[]值为0,则出现了断层,理论上就搜不到增广路了。 - 代码:
#include<bits/stdc++.h>
using namespace std;
const int N=1e4+5;
const int inf=0x3f3f3f3f;
int nxt[N],to[N],head[N],len[N],num=1;
void add_edge(int u,int v,int w) {nxt[++num]=head[u];to[num]=v;len[num]=w;head[u]=num;}
int dis[N],n,m,s,t,gap[N];
void bfs()
{
memset(dis,-1,sizeof(dis));
memset(gap,0,sizeof(gap));
dis[t]=0,gap[0]=1;
queue<int>q;
q.push(t);
while(!q.empty()) {
int u=q.front();
q.pop();
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
if(dis[v]!=-1)continue;
q.push(v);
dis[v]=dis[u]+1,gap[dis[v]]++;
}
}
return;
}
long long maxflow;
long long dfs(int u,long long flow) {
if(u==t) return flow;
long long used=0;
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
if(len[i]&&dis[v]+1==dis[u]) {
int tmp=dfs(v,min(1ll*len[i],flow-used));
if(tmp) {
len[i]-=tmp;
len[i^1]+=tmp;
used+=tmp;
}
if(used==flow)return used;
}
}
--gap[dis[u]];
if(gap[dis[u]]==0)dis[s]=n;
dis[u]++,gap[dis[u]]++;
return used;
}
long long ISAP()
{
maxflow=0;
for(bfs();dis[s]<n;maxflow+=dfs(s,inf));
return maxflow;
}
int main() {
scanf("%d%d%d%d",&n,&m,&s,&t);
int u,v,w;
for(int i=1;i<=m;i++) {
scanf("%d%d%d",&u,&v,&w);
add_edge(u,v,w);
add_edge(v,u,0);
}
printf("%lld\n",ISAP());
return 0;
}
费用流算法
- 流程:
首先变化在于,找最大流的基础上满足最小(大)费用。其次,每条边上多了费用一变量,因此我们在存反边时边的费用为负的原费用
然后我们把EK_BFS找增广路改为找最短(长)路即可。注意记录前驱,最后结束时更新边信息。 - 代码:
#include<stdio.h>
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int mxflow=0,mnval=0,dis[N],head[N],n,m,s,t,to[N],nxt[N],len[N],val[N],ecnt=1,flow[N],pre[N],inf=0x3f3f3f3f;
void add_edge(int u,int v,int z,int w) {
nxt[++ecnt]=head[u];to[ecnt]=v;len[ecnt]=z;val[ecnt]=w;head[u]=ecnt;
nxt[++ecnt]=head[v];to[ecnt]=u;len[ecnt]=0;val[ecnt]=-w;head[v]=ecnt;
}
bool In_q[N];
queue<int> Q;
void init() {
for(int i=0;i<=n;i++)dis[i]=flow[i]=inf,In_q[i]=0,pre[i]=0;
}
bool spfa() {
init();
Q.push(s); dis[s]=0,In_q[s]=1;
while(!Q.empty()) {
int u=Q.front(); Q.pop(); In_q[s]=0;
for(int i=head[u];i;i=nxt[i]) {
int v=to[i];
if(len[i]&&dis[v]>dis[u]+val[i]) {
dis[v]=dis[u]+val[i];
flow[v]=min(flow[u],len[i]);
pre[v]=i^1; //记录终点往前的边的编号
Q.push(v),In_q[v]=1;
}
}
}
if(dis[t]==0x3f3f3f3f) return false;
return true;
}
void mn_valflow() {
while(spfa()) {
mxflow+=flow[t];
mnval+=flow[t]*dis[t];
int k=t;
while(pre[k]) {
len[pre[k]]+=flow[t],len[pre[k]^1]-=flow[t];
k=to[pre[k]];
}
}
}
int main() {
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++) {
int u,v,z,w;
scanf("%d%d%d%d",&u,&v,&z,&w);
add_edge(u,v,z,w);
}
mn_valflow();
printf("%d %d",mxflow,mnval);
return 0;
}
最大流&最小割&费用流模版的更多相关文章
- hdu4289 最小割最大流 (拆点最大流)
最小割最大流定理:(参考刘汝佳p369)增广路算法结束时,令已标号结点(a[u]>0的结点)集合为S,其他结点集合为T=V-S,则(S,T)是图的s-t最小割. Problem Descript ...
- 最大流-最小割 MAXFLOW-MINCUT ISAP
简单的叙述就不必了. 对于一个图,我们要找最大流,对于基于增广路径的算法,首先必须要建立反向边. 反向边的正确性: 我努力查找了许多资料,都没有找到理论上关于反向边正确性的证明. 但事实上,我们不难理 ...
- 【BZOJ-1797】Mincut 最小割 最大流 + Tarjan + 缩点
1797: [Ahoi2009]Mincut 最小割 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1685 Solved: 724[Submit] ...
- BZOJ-1001 狼抓兔子 (最小割-最大流)平面图转对偶图+SPFA
1001: [BeiJing2006]狼抓兔子 Time Limit: 15 Sec Memory Limit: 162 MB Submit: 14686 Solved: 3513 [Submit][ ...
- HDU(2485),最小割最大流
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=2485 Destroying the bus stations Time Limit: 40 ...
- 洛谷P4014 分配问题【最小/大费用流】题解+AC代码
洛谷P4014 分配问题[最小/大费用流]题解+AC代码 题目描述 有 n 件工作要分配给 n 个人做.第 i 个人做第 j 件工作产生的效益为c ij. 试设计一个将 n 件工作分配给 n 个人做的 ...
- UVA - 10480 Sabotage【最小割最大流定理】
题意: 把一个图分成两部分,要把点1和点2分开.隔断每条边都有一个花费,求最小花费的情况下,应该切断那些边.这题很明显是最小割,也就是最大流.把1当成源点,2当成汇点,问题是要求最小割应该隔断那条边. ...
- hdu1569 方格取数(2) 最大点权独立集=总权和-最小点权覆盖集 (最小点权覆盖集=最小割=最大流)
/** 转自:http://blog.csdn.net/u011498819/article/details/20772147 题目:hdu1569 方格取数(2) 链接:https://vjudge ...
- BZOJ1001:狼抓兔子(最小割最大流+vector模板)
1001: [BeiJing2006]狼抓兔子 Description 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨, ...
随机推荐
- python---导入模块和包
导入模块和包 导入模块 import的过程中发生了哪些事情? 寻找模块 如果找到,开辟一块空间,执行这个模块 把这个模块中用到的名字都收录到开辟的空间中 创建一个变量来引用这个模块的空间 注意: 模块 ...
- OSPF 路由协议详解(一)
(文章目录) ospf 协议是网络层协议 此篇文章适合有一定网络基础的人 ospf 协议最多应用在企业网络中,针对于运营商网络并不是特别的适用,端口号为 89 通过 IP 进行数据的转发 ospf 基 ...
- 使用 mix-blend-mode 实现抖音 LOGO
<template> <div class="g-container"> <div class="j"></d ...
- Hyperledger Fabric无排序组织以Raft协议启动多个Orderer服务、TLS组织运行维护Orderer服务
前言 在实验Hyperledger Fabric无排序组织以Raft协议启动多个Orderer服务.多组织共同运行维护Orderer服务中,我们已经完成了让普通组织运行维护 Orderer 服务,但是 ...
- Angular项目构建指南 - 不再为angular构建而犹豫不决(转)
如果你不知道什么是Angular或者根本没听说过,那么我接下来所说的对你来说毫无益处,不过如果你打算以后会接触Angular或者干脆要涨涨姿势~读下去还是有点用的. Angular和它之前所出现的其余 ...
- 阶段性总结linux(1)
学习安装linux系统 [网络连接方式] 桥接 ,好比所有人都在25期教室,公用这个教室的局域网段 192.168.11.0~192.168.11.255 教室内有60个同学,插上了网线,所有人都是 ...
- python学习-Day37
目录 今日内容详细 GIL全局解释器锁 GIL与普通互斥锁区别 GIL对程序的影响 验证多线程作用 两个大前提 关于CPU的个数 关于任务的类型 死锁现象 避免死锁的解决: 添加超时释放锁 信号量 自 ...
- XCTF练习题---MISC---倒立屋
XCTF练习题---MISC---倒立屋 flag:flag{9102_cCsI} 解题步骤: 1.观察题目,下载附件 2.打开发现是个倒立的屋子,并没有发现啥东西,拿StegSolve看看 3.查了 ...
- [AcWing 788] 逆序对的数量
点击查看代码 #include<iostream> using namespace std; typedef long long ll; const int N = 1e5 + 10; i ...
- c++:-3
上一节学习了C++的函数:c++:-2,本节学习C++的数组.指针和字符串 数组 定义和初始化 定义 例如:int a[10]; 表示a为整型数组,有10个元素:a[0]...a[9] 例如: int ...