【网络流】EK算法及其优化
今天上午我仿佛知道了什么叫做网络流,这里推荐一篇博客,大家入门网络流的可以看一下这篇博客,保证一看就懂!
博客链接:
网络流入门
这里有一篇经过我改过的EK带注释代码(博客里也有一样的,只是加了一些注释),大家可以看一下:
//codevs 1993
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
const int INF=0x7ffffff;
queue <int> q;
int n,m,x,y,s,t,g[201][201],pre[201],flow[201],maxflow;
//g邻接矩阵存图,pre增广路径中每个点的前驱,flow源点到这个点的流量 (就是増广路(min))!
inline int bfs(int s,int t)
{
while (!q.empty()) q.pop();//清空!
for (int i=1; i<=n; i++) pre[i]=-1;//清空!!!
pre[s]=0;
q.push(s);
flow[s]=INF;
while (!q.empty())
{
int x=q.front();
q.pop();
if (x==t) break;
for (int i=1; i<=n; i++)
//EK一次只找一个增广路 ,这句话非常的重要啊!!!!!important! very important! very very important!!!
//不认真看这句话,不要怪下面自己看不懂!
if (g[x][i]>0 && pre[i]==-1)//如果当时x到i点有容量,并且i点还没有找到前驱
{
pre[i]=x;
flow[i]=min(flow[x],g[x][i]);//是不是觉得有一点像SPFA ??? 找最小的増广路
q.push(i);
}
}
if (pre[t]==-1) return -1;//死啦!
else return flow[t];
}
//increase为增广的流量
void EK(int s,int t)
{
int increase=0;
while ((increase=bfs(s,t))!=-1)//这里的括号加错了!Tle
{//迭代
int k=t;//k等于终点
while (k!=s)//当k不为起点时
{
int last=pre[k];//从后往前找路径
g[last][k]-=increase;//正着走残量网络要减去增广量
g[k][last]+=increase;//反之,反着走要加上增广量
k=last;
}
maxflow+=increase;//增加増广路
}
}
int main()
{
scanf("%d%d",&m,&n);//m是挖了几条沟,n是有几条汇点 ,最后一个点n也是小溪的编号
for (int i=1; i<=m; i++)
{
int z;
scanf("%d%d%d",&x,&y,&z);
g[x][y]+=z;//此处不可直接输入,要+= ,为什么???????????????important
}
EK(1,n);
printf("%d",maxflow);
return 0;
}
下面大家就会发现一个问题,用邻接矩阵存储,是不是也太费空间了,要是题目让你跑一个有10000个点的网络流岂不凉凉!!!
下面就要献上我们改装过的EK算法!(说白了就是Dinic)
#include<bits/stdc++.h>
using namespace std;
struct listx{
int to,next=0,f;
}edge[200005];
int cnt=0,n,m,s,t;
int head[10005];
int depth[10005];
void update(int num,int flow)
{
edge[num].f-=flow;
edge[num+1].f+=flow;
}
void addedge(int u,int v,int w)
{
cnt++;
edge[cnt].next=head[u];
edge[cnt].to=v;
edge[cnt].f=w;
head[u]=cnt;
}
bool bfs()
{
memset(depth,0,sizeof(depth));
queue<int>que;
while(!que.empty())
{
que.pop();
}
que.push(s);
depth[s]=1;
while(!que.empty())
{
int cur=que.front();
que.pop();
if(cur==t)
break;
for(int i=head[cur];i!=0;i=edge[i].next)
{
listx temp=edge[i];
if(depth[temp.to]==0&&temp.f>0)
{
depth[temp.to]=depth[cur]+1;
que.push(temp.to);
}
}
}
if(depth[t]==0)
return false;
return true;
}
int dfs(int u,int flow)
{
if(u==t)
return flow;
for(int i=head[u];i!=0;i=edge[i].next)
{
listx temp=edge[i];
if(depth[u]+1==depth[temp.to]&&temp.f>0)
{
flow=flow<temp.f?flow:temp.f;
int newx=dfs(temp.to,flow);
if(newx>0)
{
update(i,newx);
return newx;
}
}
}
return 0;
}
int main()
{
int ans=0;
scanf("%d%d%d%d",&n,&m,&s,&t);
for(int i=1;i<=m;i++)
{
int a1,b1,c1;
scanf("%d%d%d",&a1,&b1,&c1);
addedge(a1,b1,c1);
addedge(b1,a1,0);
}
while(bfs())
{
int k;
while(k=dfs(s,10000000))
{
ans+=k;
}
}
printf("%d",ans);
return 0;
}【网络流】EK算法及其优化的更多相关文章
- POJ 1459 网络流 EK算法
题意: 2 1 1 2 (0,1)20 (1,0)10 (0)15 (1)20 2 1 1 2 表示 共有2个节点,生产能量的点1个,消耗能量的点1个, 传递能量的通道2条:(0,1)20 (1,0) ...
- 最大网络流 EK 算法
网络流是什么类型的问题,看一道题目你就知道了 点击打开链接 . 默认具备图论的基本知识,网络流概念比较多,先看看书熟悉一下那些概念.比较好!一个寄出的网络最大流.EK算法写的. 这是一幅网络,求S ...
- 网络流EK算法模板
\(EK\)算法的思想就是每一次找一条增广路进行增广. 注意几个点: 存图时\(head\)数组要设为\(-1\). 存图的代码是这样的: inline void add(int u, int v, ...
- HDU1532 Drainage Ditches 网络流EK算法
Drainage Ditches Problem Description Every time it rains on Farmer John's fields, a pond forms over ...
- Drainage Ditches(网络流(EK算法))
计算最大流,EK算法模板题. #include <stdio.h> #include <string.h> #include <queue> using names ...
- 网络流Ek算法
例题: Flow Problem HDU - 3549 Edmonds_Karp算法其实是不断找增广路的过程. 但是在找的过程中是找"最近"的一天增广路, 而不是找最高效的一条增 ...
- HDU 3549 基础网络流EK算法 Flow Problem
欢迎参加——BestCoder周年纪念赛(高质量题目+多重奖励) Flow Problem Time Limit: 5000/5000 MS (Java/Others) Memory Limit ...
- 网络流 EK算法模板。
这篇博客讲得很好 #include<queue> #include<stdio.h> #include<string.h> using namespace std; ...
- ACM/ICPC 之 网络流入门-EK算法(参考模板)(POJ1273)
基于残留网络与FF算法的改进-EK算法,核心是将一条边的单向残留容量的减少看做反向残留流量的增加. //网络流 //EK算法 //Time:16Ms Memory:348K #include<i ...
随机推荐
- JavaWeb技术
1.简介 Java Web是用Java技术来解决相关web互联网领域的技术总和.web包括:web服务器和web客户端两部分.Java在客户端的应用有java applet,不过使用得很少,Java在 ...
- stroke和fill顺序对绘图的影响
用canvas绘制线条和填充,fill()和stroke()调用顺序直接影响绘制的结构 先调用stroke在调用fill,绘制的效果看上去lineWidth只绘制出来一半,还以为是个大问题. < ...
- es6新增的数组方法和对象
es6新增的遍历数组的方法,后面都会用这个方法来遍历数组,或者对象,还有set,map let arr=[1,2,3,4,3,2,1,2]; 遍历数组最简洁直接的方法法 for (let value ...
- 不定宽高的文字在div中垂直居中
本人在面试的时候被问到:如何使一段不定宽高的文字垂直居中呢? 现在来总结一下: 在body中写入结构 <div id="main"> <div id=&qu ...
- Android FlycoDialog 简单实用的自定义Android弹窗对话框之Dialog篇
效果图镇楼 FlycoDialog是一款非常棒的弹窗对话框处理框架,今天在这里主要讲一下他的自定义弹出对话框的功能,这里以第二幅效果图为例,图片已经放在博客最下方,X号自己随便找一个东西代替吧. ...
- 关于 “VMware Workstation 不可恢复错误- (vcpu-0)”
重装系统后第一次在 VMware Workstation 上创建虚拟机,结果出现了 VMware Workstation 不可恢复错误: (vcpu-0) 错误. 于是我们遵循它给出的提示,查看一下日 ...
- eclipse插件svn和客户端工具TortoiseSvn的版本对应关系
如果同时使用这两个软件,一定要保证版本的对应关系: 插件svn1.4.x对应TortoiseSvn 1.5.x 插件svn1.6.x对应TortoiseSvn 1.6.x 插件svn1.8.x对应To ...
- winform DataGridView 通用初始化
void DGV_Init() { //名称 类型 设备数 累计转发次数 累计转发数据数 状态 ; i < ; i++) { DataGridViewTextBoxColumn dc = new ...
- Visual Studio 2012 未找到与约束 ContractName问题,及printf unsafe问题
1.用VS 2012 创建c++项目失败,提示未找到与约束 ContractName .............的错误 解决办法:下载VS 2012 补丁,很小的一个补丁,不过很管用 地址:http: ...
- 最新DNS汇集
最近几日DNS大规模抽风,网络环境是一天比一天恶劣,于是收集了一些良心的DNS服务器地址,以备不时之需. 国内服务器: 1.OpenerDNS:42.120.21.30 2.114DNS:114.11 ...