一个网络是一张有向图,图中每条有向边
都有一个给定的权值
,成为边的容量。特别地,若
则
。图中还有两个指定的特殊点
和
分别称为源点和汇点。
设是定义在节点二元组
的实数函数,且满足:
称为网络的流函数。对于
,
称为边的流量,
成为这个边的剩余流量。
称为整个网络的流量(其中
表示源点)。
E-K算法只考虑图中所有的边,用BFS找到任意一条从
到
的路径,同时计算出路径上各边的剩余容量的最小值
,则网络的流量就可以增加到
。
E-K增广路算法的时间复杂度为,然而在实际应用中则远远到不到这个上界,效率较高,一般能够处理
规模的网络。
简单附HDU1532的代码:
#include <bits/stdc++.h>
#define inf 0x3f3f3f3f
#define Pair pair<int,int>
#define int long long
#define fir first
#define sec second
const double eps=1e7;
namespace fastIO{
#define BUF_SIZE 100000
#define OUT_SIZE 100000
//fread->read
bool IOerror=0;
//inline char nc(){char ch=getchar();if(ch==-1)IOerror=1;return ch;}
inline char nc(){
static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE;
if(p1==pend){
p1=buf;pend=buf+fread(buf,1,BUF_SIZE,stdin);
if(pend==p1){IOerror=1;return -1;}
}
return *p1++;
}
inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';}
template<class T> inline bool read(T &x){
bool sign=0;char ch=nc();x=0;
for(;blank(ch);ch=nc());
if(IOerror)return false;
if(ch=='-')sign=1,ch=nc();
for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if(sign)x=-x;
return true;
}
inline bool read(double &x){
bool sign=0;char ch=nc();x=0;
for(;blank(ch);ch=nc());
if(IOerror)return false;
if(ch=='-')sign=1,ch=nc();
for(;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0';
if(ch=='.'){double tmp=1; ch=nc();for(;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0');}
if(sign)x=-x;return true;
}
inline bool read(char *s){
char ch=nc();
for(;blank(ch);ch=nc());
if(IOerror)return false;
for(;!blank(ch)&&!IOerror;ch=nc())*s++=ch;
*s=0;
return true;
}
inline bool read(char &c){
for(c=nc();blank(c);c=nc());
if(IOerror){c=-1;return false;}
return true;
}
template<class T,class... U>bool read(T& h,U&... t){return read(h)&&read(t...);}
#undef OUT_SIZE
#undef BUF_SIZE
};using namespace fastIO;using namespace std;
const int N=2010,M=20010;
const int mod=1e9+7;
int head[N],ver[M],edge[M],Next[M],v[N],incf[N],pre[N];
int n,m,s,t,tot,maxflow;
void add(int x,int y,int z){
ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
ver[++tot]=x,edge[tot]=0,Next[tot]=head[y],head[y]=tot;
}
bool bfs(){
memset(v,0,sizeof v);
queue<int>q;
q.push(s);v[s]=1;
incf[s]=inf;//增广路各边的最小剩余容量
while(q.size()){
int x=q.front();q.pop();
for(int i=head[x];i;i=Next[i]){
if(edge[i]){
int y=ver[i];
if(v[y])continue;
incf[y]=min(incf[x],edge[i]);
pre[y]=i;
q.push(y),v[y]=1;
if(y==t)return 1;
}
}
}
return 0;
}
void update(){
int x=t;
while(x!=s){
int i=pre[x];
edge[i]-=incf[t];
edge[i^1]+=incf[t];
x=ver[i^1];
}
maxflow+=incf[t];
}
signed main(){
while(read(m,n)){
memset(head,0,sizeof head);
s=1;t=n;tot=1;maxflow=0;
for(int i=1;i<=m;i++){
int x,y,c;read(x,y,c);
add(x,y,c);
}
while(bfs())update();
printf("%lld\n",maxflow);
}
return 0;
}
本文详细介绍了网络流中的E-K增广路算法,解释了有向图、边容量、流函数等基本概念,以及如何通过寻找增广路径来最大化网络流。提供了HDU1532的代码示例,展示了算法的具体实现。

271

被折叠的 条评论
为什么被折叠?



