为与机房各位神犇同步,学习下网络流,百度一下发现竟然那么多做法,最后在两种算法中抉择,分别是Dinic和ISAP算法,问过
CA爷后得知其实效率上无异,所以决定跟随Charge的步伐学习Dinic,所以来写点心得

网络流(最大流)的做法可以进行浅显的理解:

一张图可以认为是一个排水管道,每个点为管道的交叉点,每个边的边权即是这条管道的水的容量,给定一个源点和一个汇点,源点有∞的水量供给,问汇点最大可以获得多少水,所求即为最大流

但是有点题目不一定会给定源点或者汇点,还是因题而异,而且还有很多题目需要进行拆点建图也是复杂的不行。。。(沙茶的我还需要多练多想啊)

Dinic算法:

大体上是这么一个流程:

1.利用BFS分层,即按照距离源点的最短距离来分出层次

2.在分层图上DFS增广,找出这一次的最大流量,然后累入总ans中,值得注意的是,这一阶段中没找到一个当前值now,需要将所有正向边权-now,并把其反向边权+now,这可以使得以后的增广中可以后悔,即可以把之前走错的路再走一遍,保证答案的正确性

3.不断对残余网络进行BFS,直到无法到达源点结束,每次BFS后多次DFS求值直到找不到新的路径

一个很高端详细的讲解BLOG:https://comzyh.com/blog/archives/568/

大体的框架如下:

一个最基本的模板(next数组实现)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct data{
int next,to,v;
}edge[500]={0};
int cnt=1,head[500]={0};
int q[2000],h,t;
int dis[500]={0};
int n,m,ans; void add(int u,int v,int w)
{
cnt++;
edge[cnt].next=head[u];
head[u]=cnt;
edge[cnt].to=v;
edge[cnt].v=w;
} bool bfs()
{
memset(dis,-1,sizeof(dis));
q[1]=1;dis[1]=0;
h=0;t=1;
while (h<t)
{
int j=q[++h],i=head[j];
while (i)//枚举所有与当前节点相连的
{
if (dis[edge[i].to]<0 && edge[i].v>0)//判断是否已经分层过&&是否能流(联通)
{
dis[edge[i].to]=dis[j]+1;
q[++t]=edge[i].to;
}
i=edge[i].next;
}
}
if (dis[n]>0)//如果能够到达汇点,则可以继续,否则就不能继续
return true;
else
return false;
} int dfs(int loc,int low)
{
int ans=0;
if (loc==n) return low;
int i=head[loc];
while (i)//枚举所有与当前点相连的
{
//判断 是否能流(联通) && 它下面那条个点与它是否层数+1(找路径的要求必须找下一层的点) && 当前ans是否大于0
if (edge[i].v>0 && dis[edge[i].to]==dis[loc]+1 && (ans=dfs(edge[i].to,min(low,edge[i].v))))
{
edge[i].v-=ans;//正向边-去当前值
edge[i^1].v+=ans;//反向边+上当前值 ,^1异或即反向边的位置 i为单数为i-1,为双数为i+1
return ans;
}
i=edge[i].next;
}
return 0;
} int main()
{
scanf("%d%d",&m,&n);
for (int i=1; i<=m; i++)
{
int s,e,v;
scanf("%d%d%d",&s,&e,&v);
add(s,e,v);
add(e,s,0);//因为需要反向边在建完正向边后立即建一个反向边,初值为0
}
int ans=0;
while (bfs())
{
int now;
while ((now=dfs(1,0x7fffffff)))
ans+=now;
}//Dinic
printf("%d",ans);
return 0;
}

还有很多不同的规则有不同的模板,以后会更。

2016.1.3 补。

edge【】的范围一定要计算好,好几次都是这个地方开小了,这种错误太低级了。。

建图的过程需要发散一下思维,不能仅仅局限于超级源与超级汇,很多题目的需要建一些次级的点,或者进行拆点,抑或是二分后多次建图多次判定,千变万化。

在建边的时候需要建一条反向边(一般反向初始都是0,为后续反向弧用),当然 有的时候题目中需要开始就建双向边。。要好好把握

2016.1.17补。

当前弧优化(理论上常数级优化实际上优化效果完美):

bool bfs()
{
memset(dis,-1,sizeof(dis));
q[1]=0; dis[0]=1;
h=0;t=1;
while (h<t)
{
int j=q[++h],i=head[j];
while (i)
{
if (edge[i].v>0 && dis[edge[i].to]<0)
{
dis[edge[i].to]=dis[j]+1;
q[++t]=edge[i].to;
}
i=edge[i].next;
}
}
if (dis[num]>0)
return true;
else
return false;
} long long dfs(int loc,long long low)
{
if(loc==num)return low;
long long flow,cost=0;
for(int i=cur[loc];i;i=edge[i].next)
if(dis[edge[i].to]==dis[loc]+1)
{
flow=dfs(edge[i].to,min(low-cost,edge[i].v));
edge[i].v-=flow;edge[i^1].v+=flow;
if(edge[i].v) cur[loc]=i;
cost+=flow;if(cost==low)return low;
}
if(!cost)dis[loc]=-1;
return cost;
} long long dinic()
{
long long temp=0;
while (bfs())
{
for (int i=0; i<=num; i++) cur[i]=head[i];
temp+=dfs(0,maxl);
}
return temp;
}

多路增广+炸点+当前弧优化

学习笔记 --- 最大流Dinic算法的更多相关文章

  1. 机器学习实战(Machine Learning in Action)学习笔记————08.使用FPgrowth算法来高效发现频繁项集

    机器学习实战(Machine Learning in Action)学习笔记————08.使用FPgrowth算法来高效发现频繁项集 关键字:FPgrowth.频繁项集.条件FP树.非监督学习作者:米 ...

  2. java 学习笔记之 流、文件的操作

    ava 学习笔记之 流.文件的操作 对于一些基础的知识,这里不再过多的解释, 简单的文件查询过滤操作 package com.wfu.ch08; import java.io.File; import ...

  3. 网络流之最大流Dinic算法模版

    /* 网络流之最大流Dinic算法模版 */ #include <cstring> #include <cstdio> #include <queue> using ...

  4. 机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析

    机器学习实战(Machine Learning in Action)学习笔记————07.使用Apriori算法进行关联分析 关键字:Apriori.关联规则挖掘.频繁项集作者:米仓山下时间:2018 ...

  5. 机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN)

    机器学习实战(Machine Learning in Action)学习笔记————02.k-邻近算法(KNN) 关键字:邻近算法(kNN: k Nearest Neighbors).python.源 ...

  6. [ML学习笔记] 朴素贝叶斯算法(Naive Bayesian)

    [ML学习笔记] 朴素贝叶斯算法(Naive Bayesian) 贝叶斯公式 \[P(A\mid B) = \frac{P(B\mid A)P(A)}{P(B)}\] 我们把P(A)称为"先 ...

  7. Effective STL 学习笔记 31:排序算法

    Effective STL 学习笔记 31:排序算法 */--> div.org-src-container { font-size: 85%; font-family: monospace; ...

  8. Power Network(网络流最大流 & dinic算法 + 优化)

    Power Network Time Limit: 2000MS   Memory Limit: 32768K Total Submissions: 24019   Accepted: 12540 D ...

  9. 最大流——Dinic算法

    前面花了很长时间弄明白了压入-重标记的各种方法,结果号称是O(V3)的算法测demo的时候居然TLE了一个点,看了题解发现所有人都是用Dinic算法写的,但它的复杂度O(V2E)明显高于前者,具体是怎 ...

随机推荐

  1. 第11章 Windows线程池(2)_Win2008及以上的新线程池

    11.2 Win2008以上的新线程池 (1)传统线程池的优缺点: ①传统Windows线程池调用简单,使用方便(有时只需调用一个API即可) ②这种简单也带来负面问题,如接口过于简单,无法更多去控制 ...

  2. 合唱队形2 洛谷U5874

    题目背景 上次老师挑出来的(N-K)位同学很不高兴,于是他们准备自己组建合唱队形.他们请了kkk来帮忙. 题目描述 他们安排了一个动作——手拉着手唱一首歌(就是他们围成一个圈).如果有两个相邻的同学的 ...

  3. Python创建Cocos2d-x 2.2方法

    把创建项目做成一个批处理,当创建项目时可以省时省力很多. 操作步骤 1.在 E:\cocos2d-x-2.2.1\tools\project-creator 目录下创建 create_project. ...

  4. Jedis下的ShardedJedis(分布式)使用方法(二)

    上一篇中介绍了ShardedJedis的基本使用方法以及演示了一个简单的例子,在这一篇中我们来介绍了ShardedJedis的原理. 1.ShardedJedis内部实现 首先我们来看一下Sharde ...

  5. eclipse代码自动提示设置、如何配置eclipse的代码自动提示功能(同时解决自动补全变量名的问题)?

    对于编程人员来说,要记住大量的类名或类方法的名字,着实不是一件容易的事情.如果要IDE能够自动补全代码,那将为我们编程人员带来很大帮助. eclipse代码里面的代码提示功能默认是关闭的,只有输入“. ...

  6. js常用宽高属性

    document.body.clientWidth //body对象的宽度 document.body.clientHeight //body对象的高度 document.documentElemen ...

  7. angularjs: ng-select和ng-options

    angular.js有一个很强大的指令: ng-select 它可以帮助你通过数据模型来创建select元素.它很好的支持了select标签的语法,但是却有点坑. 假设有如下一段json数据: { & ...

  8. IOS证书/私钥/代码签名/描述文件

    1.   相关资源 (1)   钥匙串程序(常用工具->钥匙串),用于创建证书请求.安装证书.导出私钥等 (2)   IOS开发中心:https://developer.apple.com/de ...

  9. mac上一键配置和安装adb驱动或者环境

    最近才使用的mac,老实说mac上要配置adb的环境不那么复杂,但是还是会让一些心不细或者动手能力不强的同学望而却步.那么到底有没有一个一键完成mac上adb和fastboot环境搭配的软件或者脚本呢 ...

  10. [每日自动更新]Hillstone 山石网科 StoneOS ISP路由表配置文件

    1.数据基于APNIC,准确有效 2.适用于StoneOS 4.0~5.5各版本 3.对APNIC数据进行路由聚合,实现最小子网 4.覆盖中国大陆地区电信.联通.移动三大运营商,长宽.电信通等二级运营 ...