网络流,最大流,EK算法

概念

最大流:

从源点流向汇点的最大流量

增广路:

一条从源点到汇点的所有边的剩余容量>=0的路径

残留网:

由网络中所有结点和剩余容量大于0的边构成的子图,这里的边包括有向边和其反向边

模板题:

洛谷p3376

code:

#include<iostream>
#include<algorithm>
#include<queue>
#include<cstring>
using namespace std;
typedef long long LL;
const int N=2e2+10,M=5e3+10,INF=0x3f3f3f3f;
//id=1,从2,3开始配对
LL n,m,ne[M<<1],h[N],e[M<<1],c[M<<1],id=1,S,T;
LL mf[N],pre[N];
void add(int u,int v,int w){
    ++id;
    e[id]=v;
    ne[id]=h[u];
    c[id]=w;
    h[u]=id;
}

bool bfs(){//找增广路
    memset(mf,0,sizeof mf);
    mf[S]=INF;
    queue<int> q;
    q.push(S);
    while(q.size()){
        int u=q.front();
        q.pop();
        for(int i=h[u];i;i=ne[i]){
            LL v=e[i],w=c[i];
            if(!mf[v]&&w){
                mf[v]=min(mf[u],w);
                pre[v]=i;//存前驱边
                q.push(v);
                if(v==T){
                    return true;
                }
            }
        }
    }
    return false;
}

LL EK(){//累加可行流
    LL flow=0;
    while(bfs()){//更新残留网
        int v=T;
        while(v!=S){
            int i=pre[v];
            c[i]-=mf[T];
            c[i^1]+=mf[T];
            v=e[i^1];
        }
        flow+=mf[T];
    }
    return flow;
}

int main(){
    cin.tie(nullptr)->sync_with_stdio(false);
    cin>>n>>m>>S>>T;
    for(int i=1;i<=m;i++){
        int u,v,w;
        cin>>u>>v>>w;
        add(u,v,w);
        add(v,u,0);
    }
    cout<<EK()<<endl;
    return 0;
}
posted @ 2025-09-13 00:27  xdhking  阅读(14)  评论(0)    收藏  举报