Skip to content

Dinic封装版 ​

cpp
struct MaxFlow{
    vector<int> e,h,ne;//链式前向星
    int n,idx,S,T;//S为源点,T为汇点
    vector<int> f,d,cur;//f存流量,d存层数,cur为弧优化,表示当前从哪条节点开始搜
    MaxFlow(){}
    MaxFlow(int n){
        init(n);
    }
    void init(int n,int S=0,int T=0){
        h.assign(n+1,-1);
        d.assign(n+1,0);
        cur.assign(n+1,0);
        e.clear();
        ne.clear();
        f.clear();
        idx=0;
        this->n=n;
        this->S=S;
        this->T=T==0?n:T;
    }
    void newEdge(int x=2){
        for(int i=0;i<x;i++){
            e.emplace_back();
            ne.emplace_back();
            f.emplace_back();
        }
    }
    void addEdge(int a,int b,int c){
        newEdge();
        e[idx]=b,f[idx]=c,ne[idx]=h[a],h[a]=idx++;
        e[idx]=a,f[idx]=0,ne[idx]=h[b],h[b]=idx++;//反向流量初始为0
    }
    bool bfs(){
        queue<int> q;
        d.assign(n+1,-1);
        q.push(S);
        d[S]=0,cur[S]=h[S];
        while(!q.empty()){
            auto u=q.front();
            q.pop();
            for(int i=h[u];~i;i=ne[i]){
                int v=e[i];
                if(d[v]==-1&&f[i]){
                    d[v]=d[u]+1;
                    cur[v]=h[v];//一开始所有边都可以搜
                    if(v==T)return true;
                    q.push(v);
                }
            }
        }
        return false;
    }
    int find(int u,int limit){//深搜,limit表示从源点流向u的最多能流的流,flow表示已经流向汇点多少流
        if(u==T)return limit;
        int flow=0;
        for(int i=cur[u];~i&&flow<limit;i=ne[i]){//flow<limit优化很重要,否则易tle
            int v=e[i];
            cur[u]=i;//弧优化更新
            if(d[v]==d[u]+1&&f[i]){
                int t=find(v,min(f[i],limit-flow));
                if(!t)d[v]=-1;//如果到达不了T,标记下次就不会走到
                f[i]-=t,f[i^1]+=t,flow+=t;
            }
        }   
        return flow;
    }
    int dinic(){
        int r=0,flow;
        while(bfs())
            while(flow=find(S,INF))r+=flow;
        return r;
    }
};