最大流&最小割&费用流模版
好久都没有搞博客了。想认真写又要准备文化课期末了。
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 现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,而且现在的兔子还比较笨, ...
随机推荐
- 在TypeScript项目中进行BDD测试
在TypeScript项目中进行BDD测试 什么是BDD? BDD(Behavior-Driven Design)是软件团队的一种工作方式,通过以下方式缩小业务人员和技术人员之间的差距: 鼓励跨角色协 ...
- js读取cookie 根据cookie名称获取值的方法
//方法1 //存在问题:如果cookie中存在 aaaname=aa;name=bb 获取name的值就会出现错误function getCookie(c_name){ if (document.c ...
- java继承时能包括静态的变量和方法吗?举例说明!
子类继承了超类定义的所有实例变量和方法包括静态的变量和方法(马克-to-win见下例),并且为它自己增添了独特的元素.子类只能有一个超类.Java不支持多超类的继承. 子类拥有超类的所有成员,但它不能 ...
- DB2表数据导出、导入及常用sql使用总结
一.DB2数据的导出: export to [path(例:D:"TABLE1.ixf)]of ixf select [字段(例: * or col1,col2,col3)] from ...
- 微信小程序拖动列表功能
WXML部分 1 <view class="index"> 2 3 <!-- 数据展示区 --> 4 <scroll-view 5 class=&qu ...
- 体验了一把最近很火的开源项目-MASA Blazor
前言 很惭愧直到去年底才接触到Blazor.那什么是Blazor呢?相信大家都看过官方文档的详细说明,另外MASA团队也有不错的说明介绍 .用官方的话说Blazor是一个交互式客户端Web UI的框架 ...
- 消息中间件MQ的学习境界和路线
在<深入理解Java类加载机制,再也不用死记硬背了>里我提到了对于一门语言的"会"的三个层次.本篇将以知识地图的形式展现学习消息中间件MQ各个层次要掌握的内容. 知识地 ...
- 设计模式之:享元模式FlyweightPattern的实现
享元模式的理解: 享元模式的定义:运用共享技术支持大量细粒度对象的复用: Flyweight Pattern Definition:Use sharing to support large numbe ...
- 实战-DRF快速写接口(认证权限频率)
实战-DRF快速写接口 开发环境 Python3.6 Pycharm专业版2021.2.3 Sqlite3 Django 2.2 djangorestframework3.13 测试工具 Postma ...
- springboot+maven实现模块化编程
1.创建新项目repo-modele 2.右键Repo_modele -> New -> Module-->next 分别创建bs-web,bs-service,bs-entity, ...