简单介绍一下,EK是每次找到一条经过的边数最少的增广路进行流量增广的算法.在每轮寻找增广路的过程中,EK算法只考虑图中f(u,v)<c(u,v)的边,任意一条能从s通到t的路径都是一条增广路。根据斜对称性,反边都是可以走的。记录下该路径上的最小残量和前驱,到达t时可以退出BFS,然后从t回溯到s更新经过的边的容量。时间复杂度:O(nm2),一般能处理103~104规模的网络。
下面证明一下EK的复杂度(可以跳过直接看下方代码).
引理1:
设fi为增广i次之后的容许流(即已经选择流过的合法网络),λk(u,v)表示fk中u到v的最短路长度,则:
λk(S,v)≤λk+1(S,v),λk(v,T)≤λk+1(v,T)
证明:
假设fk+1中一条从S到v的最短路为S→u1,⋯,→ux−1→ux,ux=v,λk+1(S,v)=x.
记ei=(ui−1,ui).
若ei在fk中同样可用,即f(ui−1,ui)<c(ui−1,ui),则λk(S,ui)≤λk(S,ui−1)+1;
若ei在fk中不可用,则ei′(ei的反向边)必然可用.而且因为ei在fk中不可用,在fk+1中变成可用,说明ei′在fk中被进行了增广使得ei可用.也就说明了ei′在S到v的最短路上,即λk(S,ui−1)=λk(S,ui)+1,也满足上面的不等式.
综上所述,λk(S,v)=λk(S,ux)≤x=λk+1(S,v)
引理2:
设边e在fk变为fk+1的增广路中,e′在fj变成fj+1的增广路中(k<j),则有:
λj(S,T)≥λk(S,T)+2
证明:
假设e=(u,v),则:λk(S,v)=λk(S,u)+1,λj(S,T)=λj(S,v)+1+λj(u,T)
由引理1:
λj(S,T)≥λk(S,v)+1+λk(u,T)=λk(S,u)+λk(u,T)+2=λk(S,T)+2
若e在k1,k2,⋯,kx中在最短增广路上,则必有j1,j2⋯使得k1<j1<k2<j2<⋯,且e′在j1,j2⋯中在最短增广路上.因为1≤λk1(S,T),λkx≤n,所以x≤4n+2.即每条边最多被增广4n+2次,而每次增广的复杂度是O(m)的,总的复杂度即为O(4n+2∗m∗m)=O(m2n).
证毕.
代码:
#include <cstdio>
#include <cstring>
const int maxn=10000+10;
const int maxm=100000+10;
const int INF=0x3f3f3f3f;
int head[maxn],to[maxm<<1],nxt[maxm<<1],val[maxm<<1];
int tot=1,maxflow=0;
int pre[maxn],minf[maxn];
int n,m,s,t;
struct Queue
{
int a[maxn];
int l,r;
Queue() {l=1,r=0;}
void push(int x) {a[++r]=x;}
void pop() {l++;}
int front() {return a[l];}
bool empty() {return l>r;}
}q;
int min(int x,int y) {return x<y?x:y;}
void add(int u,int v,int w)
{
nxt[++tot]=head[u];
head[u]=tot;
to[tot]=v;
val[tot]=w;
}
bool bfs()
{
memset(pre, 0, sizeof(pre));
pre[s]=-1;
minf[s]=INF;
q=Queue();
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
for (int i=head[u];i;i=nxt[i])
{
int v=to[i];
if (pre[v]||!val[i])
continue;
pre[v]=i;
minf[v]=min(minf[u], val[i]);
q.push(v);
if (v==t)
return 1;
}
}
return 0;
}
void update()
{
int u=t,d=minf[t];
while(u!=s)
{
int i=pre[u];
val[i]-=d;
val[i^1]+=d;
u=to[i^1];
}
maxflow+=d;
}
int main()
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for (int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u, v, w),add(v, u, 0);
}
while(bfs())
update();
printf("%d\n",maxflow);
return 0;
}