最小费用最大流

//dinic 最小费用最大流 
//只需将最大流中的bfs改为SPFA即可 
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<queue>
#define ll long long
#define ull unsigned long long
#define INF 0x3f3f3f3f
using namespace std;
int n,m,s,t,maxflow,mincost,cnt=-1;
int head[5001],pre[5001],mflow[5001],mcost[5001],vis[5001];
//pre最短路上每个点所连的前一条边 mflow源点到每个点的最大增量 mcost源点到每个点的最小费用 vis为SPFA数组 
struct uio{
    int to,nxt,flow,cost;
}edge[100001];
void add(int x,int y,int f,int c)
{
    edge[++cnt].nxt=head[x];
    edge[cnt].to=y;
    edge[cnt].flow=f;
    edge[cnt].cost=c;
    head[x]=cnt;
}
bool spfa()
{
    memset(mflow,0x3f,sizeof(mflow));
    memset(mcost,0x3f,sizeof(mcost));
    memset(vis,0,sizeof(vis));
    queue<int> que;
    que.push(s);
    mcost[s]=0;
    pre[t]=-1; 
    vis[s]=1;
    while(!que.empty())
    {
        int now=que.front();
        que.pop();
        vis[now]=0;
        for(int i=head[now];i!=-1;i=edge[i].nxt)
        {
            int y=edge[i].to;
            if(edge[i].flow>0&&mcost[y]>mcost[now]+edge[i].cost)//是正边 
            {
                mcost[y]=mcost[now]+edge[i].cost;
                pre[y]=i;
                mflow[y]=min(mflow[now],edge[i].flow);
                if(!vis[y])
                {
                    vis[y]=1;
                    que.push(y);
                }
            } 
        }    
    }
    return pre[t]!=-1;//若能增广到汇点 则其前一条边就会有标记 
}
void dinic()
{
    while(spfa())
    {
        int now=t;
        maxflow+=mflow[t];
        mincost+=mcost[t]*mflow[t];
        while(now!=s)//一直回溯到源点 
        {
            edge[pre[now]].flow-=mflow[t];
            edge[pre[now]^1].flow+=mflow[t];
            now=edge[pre[now]^1].to;
        }
    }
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1;i<=m;i++)
    {
        int u,v,w,p;
        scanf("%d%d%d%d",&u,&v,&w,&p);
        add(u,v,w,p);
        add(v,u,0,-p);
    }
    dinic();
    printf("%d %d\n",maxflow,mincost);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/water-radish/p/9280670.html