1. 程式人生 > >最大流——EK演算法

最大流——EK演算法

    EK演算法是求最大流的一種容易實現、程式碼易懂的演算法。
    EK演算法仍然是一個基於增廣路的演算法,思路非常簡單。每次從S嘗試找到一條到達T的路徑,路徑上最小的殘留量大於0,那麼我們就可以把這條路上的最小殘留量減去,累加到ans裡。繼續bfs直到找不到位置,此時ans就是最大流。
    EK增廣路演算法的時間複雜度為O(nm^2)。但是在實際運營中遠遠達不到這個上界,效率較高,一般認為,可以處理10^3~10^4內規模的網路。

//??????EK??
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
const int inf=1<<29,N=2010,M=20010;
int n,m,s,t,tot,maxflow,ver[M],edge[M],Next[M],v[N],lin[N],incf[N],pre[N];
using namespace std;
void add(int x,int y,int c){
    ver[++tot]=y;Next[tot]=lin[x];edge[tot]=c;lin[x]=tot;
    ver[++tot]=x;Next[tot]=lin[y];edge[tot]=0;lin[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=lin[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];
}
int main(){
    while(cin>>n>>m){
        memset(lin,0,sizeof(lin));
        s=1,t=n;tot=1,maxflow=0;
        for(int i=1;i<=m;++i){
            int x,y,c;scanf("%d%d%d",&x,&y,&c);
            add(x,y,c);
        }
        while(bfs()) update();
        printf("%d\n",maxflow);
    }
    return 0;
}