【模板】最小费用最大流

传送门:洛谷-【模板】最小费用最大流


题意

给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。


数据范围

对于30%的数据:N<=10,M<=10

对于70%的数据:N<=1000,M<=1000

对于100%的数据:N<=5000,M<=50000


题解

没有讲解,只有代码

#include<bits/stdc++.h>
using namespace std;
const int N=5e3+10;
const int M=5e4+10;
const int INF=0x7fffffff;
int n,m,S,T,i,j,U,V,C,W,tot=1,ans,flow,stk=1,vis[N],dis[N];
int head[N],to[M<<1],nxt[M<<1],w[M<<1],v[M<<1];
deque<int>Q;

inline int read(){
    char ch=getchar();int x=0,f=1;
    while(ch<'0' || ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    while(ch>='0' && ch<='9') {x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
    return x*f;
}

inline void lk(int U,int V,int W,int C)
{
    to[++tot]=V;nxt[tot]=head[U];head[U]=tot;w[tot]=W;v[tot]=C;
}

inline bool spfa(int s,int t)
{
    memset(vis,0,sizeof(vis));
    for(i=0;i<=n;i++) dis[i]=INF;
    dis[t]=0;vis[t]=1;
    Q.push_back(t);
    while(!Q.empty()){
        int now=Q.front();Q.pop_front();
        for(i=head[now];i;i=nxt[i]){
            if(w[i^1] && dis[to[i]]>dis[now]-v[i]){
                dis[to[i]]=dis[now]-v[i];
                if(!vis[to[i]]){
                    vis[to[i]]=1;
                    if(!Q.empty() && dis[to[i]]<dis[Q.front()]) Q.push_front(to[i]);
                    else Q.push_back(to[i]);
                }
            }
        }
        vis[now]=0;
    }
    if(dis[S]>=INF) return false;
    return true;
}

inline int dfs(int st,int f)
{
    if(st==T) {vis[T]=1;return f;}
    int sum=0,ret;vis[st]=1;
    for(int i=head[st];i;i=nxt[i]){
        if(vis[to[i]] || w[i]<=0 || dis[st]-v[i] != dis[to[i]]) continue;
        ret=dfs(to[i],min(w[i],f-sum));
        if(ret>0){
           sum+=ret;ans+=ret*v[i];w[i]-=ret;w[i^1]+=ret;
            if(sum==f)return f; 
        } 
    } 
    return sum; 
}

int mxflow()
{
    flow=0;
    while(spfa(S,T)){
        vis[T]=1;
        while(vis[T]){
            memset(vis,0,sizeof(vis));
            flow+=dfs(S,INF);
        }
    }
    return flow;
}

int main(){
    n=read(),m=read(),S=read(),T=read();
    for(i=1;i<=m;i++){
        U=read(),V=read(),W=read(),C=read();
        lk(U,V,W,C);lk(V,U,0,-C);
    }
    printf("%d ",mxflow());
    printf("%d\n",ans);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/corsica6/article/details/80158740