网络流初步

dinic  网络流算法 :

反悔边的意义:当一条流量被流入,反向流入的时候,就相当于没有流过。

分层图的意义:对于给定的点,流入< =dep[ u ] 是没有意义的,不会使得当前流更优。

当前弧优化:当前的边已经流光,不再流入。

炸点优化:当前点已经流光,设dep为-1,不再流入。

多路增广:如果一个点可以多条流出去,一次dfs多条路径。

 BFS :每次建立一个分层图。

DFS:流过一条流

 

P3376 【模板】网络最大流

模板。

网络流初步
/*
dinic最大流,复杂度上界O(V*V*E)
设置源点和汇点。
*/
#include<bits/stdc++.h>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=1e5+5;
int n,m,S,T;
struct Dinic{
    int head[N],dep[N];
    int ecnt; 
    struct edge{
        int v,flow,next;
    }e[N<<1];

    void init(){
        memset(head, -1, sizeof head);
        ecnt = 0;
    }

    void addedge(int u, int v, int  flow) {
    e[ecnt].v=v;e[ecnt].flow=flow;e[ecnt].next=head[u];head[u]=ecnt++;
    }

    bool BFS(){
        memset(dep,0,sizeof dep);
        queue<int>Q;
        Q.push(S);dep[S]=1;
        while(!Q.empty()){
            int u=Q.front();Q.pop();
            for(int i=head[u];~i;i=e[i].next){
                if(e[i].flow&&!dep[e[i].v]){
                    dep[e[i].v]=dep[u]+1;
                    Q.push(e[i].v);
                }
            }
        }
        return dep[T];
    }

    int DFS(int u, int f){
        if(u==T||f==0)return f;
        int w,used=0;
        for(int i=head[u];~i;i=e[i].next){
            if(e[i].flow&&dep[e[i].v]==dep[u]+1){
                w=DFS(e[i].v,min(f,e[i].flow));
                e[i].flow-=w;
                e[i^1].flow+=w;
                used+=w;
                f-=w;
            }
        }
        if(!used)dep[u]=-1;
        return used;
    }
    int maxflow() {
        int ans=0;
        while(BFS()){
            ans+=DFS(S,inf);
        }
        return ans;
    }
}dinic;  
int main(){
    scanf("%d %d %d %d",&n,&m,&S,&T);
    dinic.init();
    int u,v,w;
    while(m--){
        scanf("%d %d %d",&u,&v,&w);
        dinic.addedge(u,v,w);
        dinic.addedge(v,u,0);
    }

    printf("%d\n",dinic.maxflow());
    return 0;
}
View Code

 

上一篇:网络流 dinic算法


下一篇:网络流的最大流入门(从普通算法到dinic优化)