网络流
2016-10-04 21:15
197 查看
网络流(最大流)
对于网络流求最大流的问题,可以想象为从起点倒水(倒无限多的水),然后问终点的水量.所以一条路上为终点添加的流量为这条路上流量最小的路径.
(我把边能通过的流量称为流量,水的量也称为流量)
首先可以有一个贪心的想法,
每次可以让尽量大的流量通过边.
好像是已经是最大流了(已经没有水能到终点了),这种做法其实还有问题.
每次流入尽量多的水没有问题,每条边让尽量大的流量通过也没有问题,但是这样的贪心是没有远见的,它可能会把路堵住,导致答案变小(程序里的水不会自己流动).
(虽然我们可以很容易看出它的错误,但是数据一大就没有办法了,所以这样的贪心是不行的)
在普通的贪心失败后,往往可以采取回撤类型的贪心:
首先,按照前面的贪心一直加大流量.
然后,流量无法再加大了.于是,加入新的水流,让原来的水倒流回去,位新的水流腾出位置.
最后,无论如何也腾不出位置了,最大流就求出来了.
对于上个图,从3流入30的流量,但是这部分的流量没有地方去,所以让4倒流10的流量,经过5和2流向终点,并从3中得到10的流量.于是,我们增加了10的流量
这样好像很复杂(还要从源头修改),
但是这部分的操作也可以直接简化为3-5-2流动的过程
所以,在储存每一条边的时候,再额外存储一条反向边(它的可以通过的流量为0).
当水流通过时,正向边的流量减小,反向边的流向增大(表示正向可以通过的流量减小,而可以倒流的流量增大)
最后,当无法增大流量时,就求出了最大流.
const int M=1005; const int INF=1<<28; struct node { int to,cap,bk; /*e[to][bk]指向自己*/ }; struct graph { vector <node> e[M]; bool mark[M]; void clear() { for (int i=0;i<M;++i) e[i].clear();//清空; } void addedge(int st,int ed,int cap) { e[st].push_back((node){ed,cap,(int)e[ed].size()}); e[ed].push_back((node){st,0,(int)e[st].size()-1});//储存反边 (流量为0) } int dfs(int st,int ed,int f) { if (st==ed) return f; mark[st]=true; for (int i=0;i<(int)e[st].size();++i) { node &now=e[st][i]; if (mark[now.to]||!now.cap) continue; int d=dfs(now.to,ed,min(f,now.cap)); if (d) { now.cap-=d; e[now.to][now.bk].cap+=d;//为反边增加大流量 return d; } } return 0; } int flow(int st,int ed) { int flow=0; while (true) { memset(mark,0,sizeof(mark)); int f=dfs(st,ed,INF); if (!f) return flow; flow+=f; } } };
相关文章推荐
- 网络公司三误区 特劳特咨询师分析中搜机会
- 简要介绍对无线局域网络进行故障诊断
- 求你们别做网络沃尔玛好吗?
- 变电站通信网络与系统-特定通信服务映射(SCSM)
- IMS网络的功能实体介绍
- 基于arm的网络图像传输技术
- C#网络编程概述 二
- 网规:第1章 计算机网络原理-1.7网络互连
- Hyper-V 装Linux系统 网络设置问题
- 网络编程总结 iphone
- windows7创建wlan热点分享网络
- UNIX网络编程——网络IPC:套接字
- 企业内网信息泄露的防范:物理和网络泄密防范
- 网络营销之我见
- 历尽磨难与坎坷的心得------致网络…
- Win7让所有用户桌面显示系统默认图标的方法 (如:我的文档/计算机/网络)
- 14网络编程
- Docker 快速上手系列(5): 网络基础配置和容期间通信
- cocos2dx 网络连接
- Xcode7 不能使用http网络请求问题解决