继续补坑..

第三天主要是网络流

首先我们先了解一下网络流的最基本的算法:dinic

这个算法的主要做法就是这样的:

在建好的网络流的图上从源点开始向汇点跑一遍BFS,然后如果一条边的流量不为0,那么就往下标号,

每一个点的level都是上一个点的level+1

然后在跑一遍DFS,如果发现边的两个点的level差值为1(终点比起点的level大),那么就走这条边。

那么我们首先要了解一下如何建边

网络流的最基本概念就是:可以反悔

就是说假如说我们有更好的方案,那么我们可以把原来流掉的流量再流回来。

如何做到呢?就是对于每一条边连一条方向相反,流量为0的边。

下面举图说明:

这是我们网络流的图,那么假设我们一开始走的是中间那条边,那么就是这样,我们得到的最大流是3

然后接下来就是我们增广的过程啦,因为我们走过的边的反向边都加上了流量,我们首先先得到一个残量网络

然后我们在又一遍bfs后我们找到这样一条路:

所以我们最大流+3,是不是很神奇,所以答案就是6啦;

这个过程其实就是把刚才的流量反悔,把下面的这个3的流量让给下面的一条路,自己走上面的一条路。就是。上图:

所以这样就是网络流的基本算法啦。

下面贴下代码

bool bfs(){
int h=,t=;
que[h]=S;
level[S]=;
while(h<=t){
int tmp=que[h++];
for(int i=head[tmp];i;i=g[i].next){
if(level[g[i].to]==-&&g[i].w)
level[g[i].to]=level[tmp]+,que[++t]=g[i].to;
}
}
return level[T]!=-;
}
int dfs(int u,int v,int flow){
if(u==v)return flow;
int used=;
for(int i=head[u];i;i=g[i].next){
if(level[g[i].to]==level[u]+){
int qaq=dfs(g[i].to,v,min(g[i].w,flow-used));
if(qaq){
g[i].w-=qaq;g[i^].w+=qaq;used+=qaq;
if(used==flow) return flow;
}
}
}
return used;
}
int dinic(int u,int v){
memset(level,-,sizeof(level));
int tot=;
while(bfs()){
tot+=dfs(S,T,inf);
memset(level,-,sizeof(level));
}
return tot;
}

————————————————我是分割线————————————————

那么我们接下来看一看最小割。

最小割的定义就是对于一个网络流的图,删掉一些边,使得从源点没有路径可以到达汇点,而花费(删掉一条边的花费就是该边的流量)的总和的最小值就是最小割。

比如下图中红色的边就是最小割

那么我们会惊奇的发现最小割就是最大流。。(至于理论我就不证明了)

——————————————我是分割线——————————————

而对于网络流这一块来说,难的不是算法本身,而是建图这一环节:

本帖着重讲解的是最小割的建图:

对于求最小割,我们一般都是要求总收益最大的一类题目,题目一般会告诉你有很多种收益,那么我们如何根据题目建图呢?

首先我们要在脑海中有一个概念,就是说我们假如说删掉一条边,意味着我们损失了一项收益,假如说我们的题目告诉我们一个项目有两种选项A,B,那么我们假设一个点割到S(表示这个点所对应的项目与T相连的边被割断,之所以这么说是因为我们有可能把一个项目拆成多个点来建图)代表的是他选择A收益,那么就说明放弃了B收益,所以B收益就是损失的一部分。

所以对于上述类型的题目,我们从S到项目连一条流量为Ai的边,从项目向汇点连一条流量为Bi的边,然后跑最大流。然后我们把所有的收益加起来-最大流(总损失)就是我们的最大收益啦!

那么还有一种题目是如果我们同时选择几种项目才能获得一项收益,对于这种图我们怎么办呢?

对于这种图,我们需要建一个辅助节点,假设我们知道多个节点都割到S才能获得这项收益,那么我们就从这些节点向辅助节点连一条流量为inf的边(表示这些边不能被割断),然后我们再从辅助节点向T连一条流量为收益大小的边,具体上图:

图中的两个点如果只要有一个点割到T,那么辅助节点到T的边就必须被割断(损失该项收益)

而这种辅助节点建在哪一边取决于满足条件是多个点割到S还是割到T,如果是割到S,那么辅助节点在T一侧,否则在S一侧。本类型最经典的题目就是文理分科(bzoj_3894)

下面贴上该题代码

#include<cstdio>
#include<cstring>
#define min(a,b) ((a)<(b)?(a):(b))
#define inf 0x3f3f3f3f
#define MN 30005
#define M 300005
#ifndef Debug
#define getchar() (SS==TT&&(TT=(SS=BB)+fread(BB,1,1<<15,stdin),TT==SS)?EOF:*SS++)
char BB[<<],*SS=BB,*TT=BB;
#endif
using namespace std;
inline int read(){
register int x; register bool f; register char c;
for (f=; (c=getchar())<''||c>'';);
for (x=c-''; (c=getchar())>=''&&c<=''; x=(x<<)+(x<<)+c-'');
return f?-x:x;
}
int n,m,sum,S,T,num=;
int head[MN],level[MN],que[MN];
struct edge{
int to,next,w;
}g[M];
bool bfs(){
memset(level,-,sizeof(level));
int h=,t=;
que[h]=S;level[S]=;
while(h<=t){
int tmp=que[h++];
for(int i=head[tmp];i;i=g[i].next)
if(level[g[i].to]==-&&g[i].w)
level[g[i].to]=level[tmp]+,que[++t]=g[i].to;
}
return level[T]!=-;
}
int dfs(int u,int flow){
if(u==T)return flow;
int used=;
for(int i=head[u];i;i=g[i].next)
if(level[g[i].to]==level[u]+){
int qaq=dfs(g[i].to,min(g[i].w,flow-used));
if(qaq){
g[i].w-=qaq;g[i^].w+=qaq;used+=qaq;
if(used==flow)return flow;
}
}
return used;
}
int dinic(){
int ttf=;
while(bfs())ttf+=dfs(S,inf);
return ttf;
}
void ins(int u,int v,int w){g[++num].next=head[u];head[u]=num;g[num].to=v;g[num].w=w;}
void insw(int u,int v,int w){ins(u,v,w);ins(v,u,);}
void add(int x,int u){
if(u==S){
insw(n+x,x,inf);
if(x>m)insw(n+x,x-m,inf);
if(x<=n-m)insw(n+x,x+m,inf);
if(x%m!=)insw(n+x,x+,inf);
if(x%m!=)insw(n+x,x-,inf);
}
else{
insw(x,*n+x,inf);
if(x>m)insw(x-m,*n+x,inf);
if(x<=n-m)insw(x+m,*n+x,inf);
if(x%m!=)insw(x+,*n+x,inf);
if(x%m!=)insw(x-,*n+x,inf);
}
}
int main(){
scanf("%d%d",&n,&m);S=*n*m+;T=S+;n*=m;
int x;
for(int i=;i<=n;i++)scanf("%d",&x),insw(S,i,x),sum+=x;
for(int i=;i<=n;i++)scanf("%d",&x),insw(i,T,x),sum+=x;
for(int i=;i<=n;i++)scanf("%d",&x),insw(S,n+i,x),add(i,S),sum+=x;
for(int i=;i<=n;i++)scanf("%d",&x),insw(*n+i,T,x),add(i,T),sum+=x;
printf("%d\n",sum-dinic());
}

注:本题getchar快读在C++中无法运行,如要调试请删除ifndef~endif这一段,出事本人概不负责QAQ

培训补坑(day3:网络流&最小割)的更多相关文章

  1. 【题解】 bzoj3894: 文理分科 (网络流/最小割)

    bzoj3894,懒得复制题面,戳我戳我 Solution: 首先这是一个网络流,应该还比较好想,主要就是考虑建图了. 我们来分析下题面,因为一个人要么选文科要么选理科,相当于两条流里面割掉一条(怎么 ...

  2. 【bzoj3774】最优选择 网络流最小割

    题目描述 小N手上有一个N*M的方格图,控制某一个点要付出Aij的代价,然后某个点如果被控制了,或者他周围的所有点(上下左右)都被控制了,那么他就算是被选择了的.一个点如果被选择了,那么可以得到Bij ...

  3. 【bzoj1143】[CTSC2008]祭祀river Floyd+网络流最小割

    题目描述 在遥远的东方,有一个神秘的民族,自称Y族.他们世代居住在水面上,奉龙王为神.每逢重大庆典, Y族都会在水面上举办盛大的祭祀活动.我们可以把Y族居住地水系看成一个由岔口和河道组成的网络.每条河 ...

  4. 【bzoj1797】[Ahoi2009]Mincut 最小割 网络流最小割+Tarjan

    题目描述 给定一张图,对于每一条边询问:(1)是否存在割断该边的s-t最小割 (2)是否所有s-t最小割都割断该边 输入 第一行有4个正整数,依次为N,M,s和t.第2行到第(M+1)行每行3个正 整 ...

  5. 【bzoj1976】[BeiJing2010组队]能量魔方 Cube 网络流最小割

    题目描述 一个n*n*n的立方体,每个位置为0或1.有些位置已经确定,还有一些需要待填入.问最后可以得到的 相邻且填入的数不同的点对 的数目最大. 输入 第一行包含一个数N,表示魔方的大小. 接下来 ...

  6. 【bzoj4177】Mike的农场 网络流最小割

    题目描述 Mike有一个农场,这个农场n个牲畜围栏,现在他想在每个牲畜围栏中养一只动物,每只动物可以是牛或羊,并且每个牲畜围栏中的饲养条件都不同,其中第i个牲畜围栏中的动物长大后,每只牛可以卖a[i] ...

  7. 【bzoj3438】小M的作物 网络流最小割

    原文地址:http://www.cnblogs.com/GXZlegend/p/6801522.html 题目描述 小M在MC里开辟了两块巨大的耕地A和B(你可以认为容量是无穷),现在,小P有n中作物 ...

  8. 【bzoj3144】[Hnoi2013]切糕 网络流最小割

    题目描述 输入 第一行是三个正整数P,Q,R,表示切糕的长P. 宽Q.高R.第二行有一个非负整数D,表示光滑性要求.接下来是R个P行Q列的矩阵,第z个 矩阵的第x行第y列是v(x,y,z) (1≤x≤ ...

  9. 【bzoj3894】文理分科 网络流最小割

    原文地址:http://www.cnblogs.com/GXZlegend 题目描述 文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠结过) 小P所在的班级要进行文理分科.他的班级可以用 ...

随机推荐

  1. python学习之map函数和reduce函数的运用

    MapReduce:面向大型集群的简化数据处理引文 map()函数 Python中的map()函数接收两个参数,一个是调用函数对象(python中处处皆对象,函数未实例前也可以当对象一样调用),另一个 ...

  2. 第二章习题 C++

    1.编写一个程序,显示您的姓名和地址. #include<iostream> using namespace std; int main() { ]; cout << &quo ...

  3. 图像的模糊-opencv

    调用两个API,一个是均值模糊,一个是高斯模糊.如下所示: #include<opencv2/opencv.hpp> #include<iostream> using name ...

  4. Description POJ1703

    Description The police office in Tadu City decides to say ends to the chaos, as launch actions to ro ...

  5. dex2oat 加载多次

    我是一个做插件开发的人员,插件就是动态加载dex文件. 然后4.4以后,Android dalvik虚拟机,和ART. art运行的必须要把dex转换为oat elf文件. 然后,这个dex2oat需 ...

  6. 如何在react里嵌入iframe?

    无法访问iframe地址 index.js文件 import React from 'react'; import ReactDOM from 'react-dom'; import App from ...

  7. Eclipse 修改字符集---Eclipse教程第02课

    默认情况下 Eclipse 字符集为 GBK,但现在很多项目采用的是 UTF-8,这是我们就需要设置我们的 Eclipse 开发环境字符集为 UTF-8, 设置步骤如下: 在菜单栏选择 Window ...

  8. 使用java去对比2个带数学公式的字符串

    首先大家看到这个题目,可能会不屑一顾,呵呵,是的,起初我也认为这是个很简单的任务,当任务拿到手里后,经过我作为程序员来讲已经磨炼的无比通透的大脑来讲发现这其实是个坑. 故事的起因是这样的,想开发一款给 ...

  9. Canvas 剪切图片

    /** * 剪切图像 */ function initDemo8(){ var canvas = document.getElementById("demo8"); if (!ca ...

  10. IDEA调试快捷键

    F9            resume programe 恢复程序 F8            Step Over 相当于eclipse的f6      跳到下一步 Ctrl+Shift+F,全局查 ...