图论--网络流初步(最大流,增广路)

以下内容为提高+难度。
首先,以一个问题来引入算法:

最大流问题,该问题描述如下:
管道网络中每条边的最大通过能力(容量)是有限的,实际流量不超过容量。
最大流问题(maximum flow problem),一种组合最优化问题,就是要讨论如何充分利用装置的能力,使得运输的流量最大,以取得最好的效果。

关于最大流问题还有许多定义,具体参见紫书(算法竞赛入门经典)的P366,有详细说明(或者戳这里)。


对于这个问题,有一个十分经典的算法:增广路算法。
这个算法每次找到一条路径,记这条路径上的残量最小值为f(f>=1),则将这条路径上的边的残量都减小f,并将总流量flow也增加f。如此重复,直到没有增广路为止,此时的flow便是最大流。
然后,解决这个问题,比较有效的方法–最短增广路算法,即每次沿着最短的一条增广路进行增广。
有一种比较优秀的这种算法,Dinic算法。
我对这个算法还没有清晰的认识,所以我只是贴一下代码(洛谷 P2936 [USACO09JAN]全流Total Flow
code:

#include<bits/stdc++.h>
using namespace std;
const int maxn=10001;
inline int toint(char ch){
    if(ch>='A'&&ch<='Z'){
        return ch-'A'+1;
    }
    else{
        return ch-'a'+27;
    }
}
struct edge{
    int from,to,cap,flow;
};
int n,m,s=1,t=toint('Z');
vector<edge> edges;
vector<int> G[maxn];
inline void addedge(int from,int to,int cap){
    edges.push_back((edge){from,to,cap,0});
    edges.push_back((edge){to,from,0,0});
    int m=edges.size();
    G[from].push_back(m-2);
    G[to].push_back(m-1);
}
bool vis[maxn];
int d[maxn];
int cur[maxn];
bool bfs(){
    memset(vis,0,sizeof(vis));
    queue<int> q;
    q.push(s);
    vis[s]=1;
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=0;i<G[x].size();i++){
            edge& e=edges[G[x][i]];
            if(!vis[e.to]&&e.flow<e.cap){
                vis[e.to]=1;
                q.push(e.to);
                d[e.to]=d[x]+1;
            }
        }
    }
    return vis[t];
}
int dfs(int x,int a){
    if(x==t||a==0){
        return a;
    }
    int flow=0,f;
    for(int& i=cur[x];i<G[x].size();i++){
        edge& e=edges[G[x][i]];
        if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0){
            e.flow+=f;
            edges[G[x][i]^1].flow-=f;
            flow+=f;
            a-=f;
            if(a==0)break;
        }
    }
    return flow;
}
int Maxflow(){
    int flow=0;
    while(bfs()){
        memset(cur,0,sizeof(cur));
        flow+=dfs(s,0x3f3f3f3f);
    }
    return flow;
}
int main(){
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        char ch1,ch2;
        int x,y,l;
        cin>>ch1>>ch2>>l;
        x=toint(ch1);
        y=toint(ch2);
        addedge(x,y,l);
    }
    printf("%d",Maxflow());
    return 0;
}

这里再给一道模板题:洛谷 P3376 【模板】网络最大流
end

原文地址:https://www.cnblogs.com/stone41123/p/7581287.html