网络流最大流(Ford-Fulkson方法以及Edmond-Karp算法)

Ford-Fulkson(简称FF)方法是由Ford和Fulkson两位数学家发明的。充分利用了最小割最大流定理,并创造性的发明了回退边,使得增广路成为一种动态修改的过程,并且保证了最终结果的正确性。

FF方法的具体步骤:

(1).初始化网络中所有边的容量,c<u,v>继承该边的容量,c<u,v>初始化为0,其中边<v,u>为回退边。初始化最大流为0.

(2).在残留网络中找一条从源S到汇T的增广路p。如果找到,转步骤(3);如果不能找到,则转步骤(5).

(3).在增广路p中找到所谓的“瓶颈”边,即路径中容量最小的边,记录下这个值X,并且累加到最大流中,转步骤(4)

(4).将增广路中所有c<u,v>减去X,所有c<v,u>加上X,构成新的残留网络。转步骤(2).

(5).得出网络的最大流,退出。

附上代码(bfs):


#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>

using namespace std;

const int maxn=110;
const int inf=0x3f3f3f3f;

int map[maxn][maxn],n,m,p[maxn];

bool ek_bfs(int start,int end)
{
    queue<int>que;
    bool flag[maxn];
    memset(flag,false,sizeof(flag));
    memset(p,-1,sizeof(p));
    que.push(start);
    flag[start]=true;
    while(!que.empty()){
        int e=que.front();
        que.pop();
        if(e==end){
            return true;
        }
        for(int i=1;i<=n;i++){
            if(map[e][i]&&!flag[i]){
                flag[i]=true;
                p[i]=e;
                que.push(i);
            }
        }
    }
    return false;
}

int ek_max_flow(int start,int end)
{
    int u,flow_ans=0,mn;
    while(ek_bfs(start,end)){
        mn=inf;
        u=end;
        while(p[u]!=-1){
            mn=min(mn,map[p[u]][u]);
            u=p[u];
        }
        flow_ans+=mn;
        u=end;
        while(p[u]!=-1){
            map[p[u]][u]-=mn;
            map[u][p[u]]+=mn;
            u=p[u];
        }
    }
    return flow_ans;
}

int main()
{
    scanf("%d%d",&n,&m);
    int u,v,w;
    for(int i=1;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        map[u][v]=w;
    }
    for(int i=1;i<=4;i++){
        for(int j=1;j<=4;j++){
            cout<<map[i][j]<<" ";
        }
        cout<<endl;
    }
    int ans=ek_max_flow(1,4);
    printf("%d\n",ans);
    return 0;
}

附上代码(dfs):

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>

using namespace std;

const int inf=0x3f3f3f3f;
const int maxn=110;

struct edge{
    int to,cap,rev;
};

vector<edge>G[maxn];
bool used[maxn];

void add_edge(int from,int to,int cap)
{
    G[from].push_back((edge){to,cap,G[to].size()});
    G[to].push_back((edge){from,0,G[from].size()-1});
}

int dfs(int v,int t,int f)
{
    if(v==t){
        return f;
    }
    used[v]=true;
    for(int i=0;i<G[v].size();i++){
        edge &e=G[v][i];
        if(!used[e.to]&&e.cap>0){
            int d=dfs(e.to,t,min(f,e.cap));
            if(d>0){
                e.cap-=d;
                G[e.to][e.rev].cap+=d;
                return d;
            }
        }
    }
    return 0;
}

int max_flow(int s,int t)
{
    int flow=0;
    for(;;){
        memset(used,0,sizeof(used));
        int f=dfs(s,t,inf);
        if(f==0){
            return flow;
        }
        flow+=f;
    }
}

int main()
{
    int n,m;
    scanf("%d%d",&n,&m);
    int u,v,w;
    for(int i=0;i<m;i++){
        scanf("%d%d%d",&u,&v,&w);
        add_edge(u,v,w);
    }
    int ans=max_flow(1,4);
    cout<<ans<<endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouzi2018/article/details/81749197