#网络流,费用流#洛谷 3381 【模板】最小费用最大流

题目

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


分析

这里写图片描述
spfa然后修改每次的流量。


代码

#include <cstdio>
#include <queue>
using namespace std;
struct node{int y,next,w,c;}e[100005]; bool v[5001];
int dis[5001],answer,ans,x,y,w,c,n,m,s,t,k=1,ls[5001],pre[5001];
void add(int x,int y,int w,int c){
    e[++k].y=y; e[k].w=w; e[k].c=c; e[k].next=ls[x]; ls[x]=k;
    e[++k].y=x; e[k].w=0; e[k].c=-c;e[k].next=ls[y]; ls[y]=k;
}
bool spfa(){//spfa
    queue<int>q; 
    for (int i=1;i<=n;i++) v[i]=0;
    for (int i=1;i<=n;i++) dis[i]=707406378;
    dis[s]=0; v[s]=1; q.push(s);
    while (q.size()){
        int u=q.front(); q.pop();
        for (int i=ls[u];i;i=e[i].next)
        if (e[i].w>0&&dis[u]+e[i].c<dis[e[i].y]){//有容量且费用更少吗
            dis[e[i].y]=dis[u]+e[i].c; pre[e[i].y]=i;//记录前驱
            if (!v[e[i].y]) v[e[i].y]=1,q.push(e[i].y);
        }
        v[u]=0;
    }
    if (dis[t]<707406378) return 1; else return 0;
}
void update(){
    m=2147483647; int x=t;
    while (x!=s) m=min(m,e[pre[x]].w),x=e[pre[x]^1].y;//统计
    ans+=dis[t]*m; answer+=m; x=t; 
    while (x!=s) e[pre[x]].w-=m,e[pre[x]^1].w+=m,x=e[pre[x]^1].y;//回去修改
}
int main(){
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for (int i=1;i<=m;i++) scanf("%d%d%d%d",&x,&y,&w,&c),add(x,y,w,c);
    while (spfa()) update();
    return !printf("%d %d",answer,ans);
}

猜你喜欢

转载自blog.csdn.net/sugar_free_mint/article/details/80773514