图论:网络流最大流dinic算法

增添了弧优化,bfs提前判断

点击查看折叠代码块
/*
时间复杂度:
O(N*N*M)
*/
#include <bits/stdc++.h>

#define DEBUG
#define d1(x) std::cout << #x " = " << (x) << std::endl
#define d2(x, y) std::cout << #x " = " << (x) << " ," #y " = " << (y) << std::endl
#define disp(arry, fr, to) 
    { 
        std::cout << #arry " : "; 
        for(int _i = fr; _i <= to; _i++) std::cout << arry[_i] << " "; 
        std::cout << std::endl; 
    }

#define ed end()
#define bg begin()
#define mp make_pair
#define pb push_back
#define vv(T) v(v(T))
#define v(T) vector<T>
#define all(x) x.bg,x.ed
#define newline puts("")
#define si(x) ((int)x.size())
#define rep(i,n) for(int i=1;i<=n;++i)
#define rrep(i,n) for(int i=0;i<n;++i)
#define srep(i,s,t) for(int i=s;i<=t;++i)
#define drep(i,s,t) for(int i=t;i>=s;--i)

using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int maxn = 2e5+10;
const int inf = 0x7f7f7f7f;
const ll inf_ll = 1ll*inf*inf;
const int Mod = 1e9+7;
const double eps = 1e-7;

int head[maxn*2],cnt=0;
struct edge{
    int v,next;
    ll c;
}e[maxn*10];

void add(int u,int v,ll c){
    e[cnt].v=v;e[cnt].c=c;e[cnt].next=head[u];head[u]=cnt++;
    e[cnt].v=u;e[cnt].c=0;e[cnt].next=head[v];head[v]=cnt++;
}

int n,m;
int s,t;
int dis[maxn];
int cur[maxn];

bool bfs(int s,int t){
    memset(dis,-1,sizeof(dis));
    dis[s] = 0;
    cur[s]=head[s];
    queue<int>q;
    q.push(s);

    while(!q.empty()){
        int u=q.front();
        q.pop();
        for (int i=head[u];~i;i=e[i].next){
            int v=e[i].v;
	    ll c=e[i].c;
            if(c && dis[v]==-1){
                dis[v]=dis[u]+1;
                cur[v]=head[v];
                q.push(v);
                if(v == t) return 1;
            }
        }
    }
    return dis[t]!=-1;
}

ll dfs(int u,int t,ll flow){
    if(u==t) return flow;
    ll delta = flow;
    for (int i=cur[u];~i;i=e[i].next){
        cur[u] = i;
        int v=e[i].v;
	ll c=e[i].c;
        if(c>0 && dis[v]==dis[u]+1){
            ll d=dfs(v,t,min(c,delta));
            if(!d) dis[v]=0;
            e[i].c-=d;
            e[i^1].c+=d;
            delta-=d;
            if(delta==0) break;
        }
    }
    return flow-delta;
}

ll dinic(int s,int t){
    ll ans=0;
    while(bfs(s,t)){
        //memcpy(cur,head,sizeof(cur));
        ans+=dfs(s,t,inf);
    }
    return ans;
}

int main(){
    memset(head,-1,sizeof(head));
	cnt=0;
	scanf("%d%d%d%d",&n,&m,&s,&t);
	rep(i,m){
		int u,v;
		ll c;
		scanf("%d%d%lld",&u,&v,&c);
		add(u,v,c);
	}
	ll ans = dinic(s,t);
	printf("%lld
",ans);
    return 0;
}
你将不再是道具,而是成为人如其名的人
原文地址:https://www.cnblogs.com/wsl-lld/p/13393588.html