luogu P3376 【模板】网络最大流 |Dinic

题目描述

如题,给出一个网络图,以及其源点和汇点,求出其网络最大流。

输入格式

第一行包含四个正整数 \(n,m,s,t\),分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含三个正整数 \(u_i,v_i,w_i\)​,表示第 \(i\) 条有向边从 \(u_i\) 出发,到达 \(v_i\),边权为 \(w_i\)​(即该边最大流量为 \(w_i\))。

输出格式

一行,包含一个正整数,即为该网络的最大流。


已加入当前弧优化

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e4+5,M=2e5+5,inf=1<<30;
int nxt[M],head[N],go[M],edge[M],tot=1;
inline void add(int u,int v,int w){
    nxt[++tot]=head[u],head[u]=tot,go[tot]=v,edge[tot]=w;
    nxt[++tot]=head[v],head[v]=tot,go[tot]=u,edge[tot]=0;
}
int n,m,s,t,maxflow;
int d[N],now[N];
bool bfs(){
    queue<int>q;
    memset(d,0,sizeof(d));
    q.push(s); d[s]=1;
    now[s]=head[s];
    while(q.size()){
        int u=q.front(); q.pop();
        for(int i=head[u];i;i=nxt[i]){
            int v=go[i];
            if(edge[i]&&!d[v]){
                q.push(v);
                d[v]=d[u]+1;
                now[v]=head[v];
                if(v==t)return 1;
            }
        }
    }
    return 0;
}
int dinic(int u,int flow){
    if(u==t)return flow;
    for(int &i=now[u];i;i=nxt[i]){
        int v=go[i];
        if(edge[i]&&d[v]==d[u]+1){
            int k=dinic(v,min(flow,edge[i]));
            if(!k)d[v]=0;
            else{
                edge[i]-=k;
                edge[i^1]+=k;
                return k;
            }
        }
    }
    return 0;
}
signed main(){
    cin>>n>>m>>s>>t;
    for(int i=1,u,v,w;i<=m;i++){
        scanf("%d%d%d",&u,&v,&w);
        add(u,v,w);
    }
    int flow=0;
    while(bfs())
    while(flow=dinic(s,inf))maxflow+=flow;
    cout<<maxflow<<endl;
}

猜你喜欢

转载自www.cnblogs.com/naruto-mzx/p/12918748.html