最小费用最大流

在网络流的基础上,在每条边上增加一个单位流量费用的限制,这样的问题就是最小费用最大流。

解决该问题的算法时基于贪心的思想,每次找到从源点到会点费用最小的增广路径,直到不存在增广路为止。

P3381 【模板】最小费用最大流
参考代码

#include<bits/stdc++.h>
using namespace std;
const int N=5e3+10;
const int M=2*5e4+10;
int head[N],cnt=1;
struct{
    int v,next,w,c;
}e[M];
int n,m,s,t;
inline void add(int u,int v,int w,int c){
    e[++cnt].c=c;
    e[cnt].next=head[u];
    head[u]=cnt;
    e[cnt].v=v;
    e[cnt].w=w;
}
int pren[N],prem[N],vis[N],dist[N],flow[N];
queue<int>q;
bool spfa(){
    memset(vis,0,sizeof(vis));
    memset(dist,0x3f,sizeof(dist));
    q.push(s);vis[s]=1;flow[s]=INT_MAX;
    dist[s]=0;
    int u,v,w,c;
    while(q.size()){
        u=q.front();q.pop();vis[u]=0;
        for(int i=head[u];i;i=e[i].next){
            v=e[i].v;w=e[i].w;c=e[i].c;
            if(w&&dist[v]>dist[u]+c){
                dist[v]=dist[u]+c;
                pren[v]=u;
                prem[v]=i;
                flow[v]=min(flow[u],w);
                if(!vis[v]){
                    vis[v]=1;
                    q.push(v);
                }
            }
        }
    }
    return dist[t]!=0x3f3f3f3f;
}
int ans=0,cost;
void mcmf(){
    while(spfa()){
      //  printf("%d %d\n",flow[t],dist[t]);
        int now=t,f=flow[t];
        ans+=f;cost+=f*dist[t];
        while(now!=s){
            e[prem[now]].w-=f;
            e[prem[now]^1].w+=f;
            now=pren[now];
        }
    }
    return ;
}
int main(){
    scanf("%d%d%d%d",&n,&m,&s,&t);
    int u,v,w,c;
    for(int i=1;i<=m;++i){
        scanf("%d%d%d%d",&u,&v,&w,&c);
        add(u,v,w,c);add(v,u,0,-c);
    }
    mcmf();
    printf("%d %d",ans,cost);
    return 0;
}
posted @ 2022-08-13 22:09  何太狼  阅读(82)  评论(0编辑  收藏  举报