运维开发网

【模板】最小费用最大流

运维开发网 https://www.qedev.com 2020-07-23 10:47 出处:网络 作者:运维开发网整理
洛咕 题意:如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用.\(N<=5000,M<=50000.\) 分析:在\(EK\)算法求解最大流的基础上,把"用BFS任意寻找一条增广路"改为"用\(SPFA\)寻找一条单位流量费用之和最小的增广路"(也就是把\(w(x,y)\)当做边权,在残量网络上求最短路)即可求出最小费用最大流.

洛咕

题意:如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用.\(N<=5000,M<=50000.\)

分析:在\(EK\)算法求解最大流的基础上,把"用BFS任意寻找一条增广路"改为"用\(SPFA\)寻找一条单位流量费用之和最小的增广路"(也就是把\(w(x,y)\)当做边权,在残量网络上求最短路)即可求出最小费用最大流.

注意:一条反向边\((y,x)\)的费用应设为\(-w(x,y)\).

最大费用最大流就把最短路改成最长路即可.

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define ll long long
using namespace std;
inline int read(){
    int x=0,o=1;char ch=getchar();
    while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    if(ch=='-')o=-1,ch=getchar();
    while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
    return x*o;
}
const int N=5005;
const int M=100005;
int n,m,s,t,max_flow,ans;
int dis[N],visit[N],incf[N],pre[N];
int tot=1,head[N],nxt[M],to[M],limit[M],w[M];
inline void add(int a,int b,int c,int d){
    nxt[++tot]=head[a];head[a]=tot;
    to[tot]=b;limit[tot]=c;w[tot]=d;
}
inline bool spfa(){
    for(int i=1;i<=n;++i)visit[i]=0,dis[i]=1e9;
    queue<int>q;q.push(s);
    dis[s]=0;visit[s]=1;incf[s]=1e9;
    while(q.size()){
        int u=q.front();q.pop();visit[u]=0;
        for(int i=head[u];i;i=nxt[i]){
            if(!limit[i])continue;
            int v=to[i];
            if(dis[v]>dis[u]+w[i]){
                dis[v]=dis[u]+w[i];
                incf[v]=min(incf[u],limit[i]);
                pre[v]=i;
                if(!visit[v])visit[v]=1,q.push(v);
            }
        }
    }
    if(dis[t]==1e9)return false;
    return true;
}
inline void update(){
    int x=t;
    while(x!=s){
        int i=pre[x];
        limit[i]-=incf[t];
        limit[i^1]+=incf[t];
        x=to[i^1];
    }
    max_flow+=incf[t];
    ans+=dis[t]*incf[t];
}
int main(){
    n=read();m=read();s=read();t=read();
    for(int i=1;i<=m;++i){
        int a=read(),b=read(),w=read(),v=read();
        add(a,b,w,v);add(b,a,0,-v);
    }
    while(spfa())update();
    printf("%d %d\n",max_flow,ans);
    return 0;
}
0

精彩评论

暂无评论...
验证码 换一张
取 消