洛谷P3381

原题链接

题意简述

模板题啦~

题解

每次都以费用作为边权求一下最短路,然后沿着最短路增广。

Code

//【模板】最小费用最大流
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
inline char gc()
{
    static char now[1<<16],*S,*T;
    if(S==T) {T=(S=now)+fread(now,1,1<<16,stdin); if(S==T) return EOF;}
    return *S++;
}
inline int read()
{
    int x=0,f=1; char ch=gc();
    while(ch<'0'||'9'<ch) {if(ch=='-') f=-1; ch=gc();}
    while('0'<=ch&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int const N=5e3+10;
int const M=5e4+10;
int const INF=0x3F3F3F3F;
int n,m,s,t;
int cnt,h[N];
struct edge{int v,c,w,nxt;} ed[M<<1];
void edAdd(int u,int v,int c,int w)
{
    ++cnt; ed[cnt].v=v,ed[cnt].c=c,ed[cnt].w=w; ed[cnt].nxt=h[u],h[u]=cnt;
    ++cnt; ed[cnt].v=u,ed[cnt].c=0,ed[cnt].w=-w; ed[cnt].nxt=h[v],h[v]=cnt;
}
int dst[N],pre[N]; int q[N],op,cl; bool in[N];
bool SPFA()
{
    op=cl=0;
    memset(dst,0x3F,sizeof dst);
    memset(pre,0,sizeof pre);
    dst[s]=0; in[q[++cl%N]=s]=true;
    while(op<cl)
    {
        int u=q[++op%N]; in[u]=false;
        for(int i=h[u];i;i=ed[i].nxt)
        {
            int v=ed[i].v,w=ed[i].w;
            if(dst[u]+w<dst[v] && ed[i].c)
            {
                pre[v]=i; dst[v]=dst[u]+w;
                if(!in[v]) in[q[++cl%N]=v]=true;
            }
        }
    }
    return dst[t]<INF;
}
int main()
{
    n=read(),m=read(); s=read(),t=read();
    cnt=1;
    for(int i=1;i<=m;i++)
    {
        int u=read(),v=read(),c=read(),w=read();
        edAdd(u,v,c,w);
    }
    int flow=0,cost=0;
    while(SPFA())
    {
        int fl=INF,u=t;
        while(pre[u]) fl=min(fl,ed[pre[u]].c),u=ed[pre[u]^1].v;
        flow+=fl; cost+=fl*dst[t];
        u=t;
        while(pre[u]) ed[pre[u]].c-=fl,ed[pre[u]^1].c+=fl,u=ed[pre[u]^1].v;
    }
    printf("%d %d
",flow,cost);
    return 0;
}
原文地址:https://www.cnblogs.com/VisJiao/p/8485761.html