P3381 【模板】最小费用最大流

【题意】

最小费用最大流

【分析】

用spfa代替bfs,然后用EK算法增广即可

【代码】

#include<bits/stdc++.h>
using namespace std;
int n,m,s,t;
const int maxn=5e3+5;
const int inf=pow(2,31)-1;
const int maxm=5e4+5;
struct edge
{
    int u,to,nxt,v,w;
}e[maxm<<1];
int head[maxn],cnt=1;
void add(int x,int y,int a,int b)
{
    e[++cnt].nxt=head[x];
    e[cnt].to=y;
    e[cnt].u=x;
    e[cnt].v=a;
    e[cnt].w=b;
    head[x]=cnt;
}
int vis[maxn],dis[maxn],pre[maxn];
bool spfa()
{
    memset(vis,0,sizeof(vis));
    memset(dis,0x3f,sizeof(dis));
    memset(pre,-1,sizeof(pre));
    dis[s]=0;
    queue <int> q;
    q.push(s);
    vis[s]=1;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].nxt)
        {
            if(!e[i].v) continue;
            int to=e[i].to;
            if(dis[u]+e[i].w<dis[to])
            {
                dis[to]=dis[u]+e[i].w;
                pre[to]=i;
                if(!vis[to])
                {
                    q.push(to);
                    vis[to]=1;
                }
            }
        }
    }
    return (pre[t]!=-1);
}
void mcmf()
{
    int ans=0,res=0;
    while(spfa())
    {
        int flow=inf;
        for(int i=t;i!=s;i=e[pre[i]^1].to)
            flow=min(flow,e[pre[i]].v);
        for(int i=t;i!=s;i=e[pre[i]^1].to)
        {
            e[pre[i]].v-=flow;
            e[pre[i]^1].v+=flow;
            res+=e[pre[i]].w*flow;
        }
        ans+=flow;
    }
    printf("%d %d\n",ans,res);
}
int main()
{

    scanf("%d%d%d%d",&n,&m,&s,&t);
    int x,y,z,w;
    memset(head,-1,sizeof(head));
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&x,&y,&z,&w);
        add(x,y,z,w); add(y,x,0,-w);
    }
    mcmf();
    return 0;
}

 

posted @ 2021-06-06 11:32  andyc_03  阅读(44)  评论(0编辑  收藏  举报