最小费用流

/*

题目:
    求最小费用最大流的裸模板

分析:
    每次找到一条最短路,然后记录下每个经过的节点的前驱结点,然后若能够
    到达终点的话,从终点开始往回找到最小流,然后再从终点往回依次更改当
    前每条边的流量以及反向弧,直到不能再找到一条最短路为止,找最短路的
    算法是spfa

*/
#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

const int maxn = 10005;
const int maxm = 1000005;
const int inf = 1e8;
#define debug puts("here");

int n,m,s,t,cas,ans,cl,aug;
int dis[maxn],pre[maxn],po[maxn];
bool use[maxn];
int q[maxm],head,tail;

struct node
{
    int y,next,f,c;
}edge[maxm];

void add(int x,int y,int f,int c)
{
    edge[++cl].y = y;
    edge[cl].f = f;
    edge[cl].c = c;
    edge[cl].next = po[x];
    po[x] = cl;

    edge[++cl].y = x;
    edge[cl].f = 0;
    edge[cl].c = -c;
    edge[cl].next = po[y];
    po[y] = cl;
}

int spfa()
{
    memset(use,false,sizeof(use));
    for(int i=0;i<=n;i++)
        dis[i] = inf;
    head = tail = 0;
    q[tail++] = s;
    dis[s] = 0;
    pre[s] = 0;
    int x,y;
    while(head<tail)
    {
        x = q[head++];
        use[x] = false;
        for(int i=po[x];i;i=edge[i].next)
        {
            y = edge[i].y;
            if(edge[i].f>0&&edge[i].c+dis[x]<dis[y])
            {
                dis[y] = edge[i].c+dis[x];
                pre[y] = i;
                if(!use[y])
                {
                    q[tail++] = y;
                    use[y] = true;
                }
            }
        }
    }
    if(dis[t]==inf)
        return false;
    aug = inf;
    for(int i=pre[t];i;i=pre[edge[i^1].y])
        aug = min(aug,edge[i].f);
    for(int i=pre[t];i;i=pre[edge[i^1].y])
    {
        edge[i].f -= aug;
        edge[i^1].f += aug;
    }
    ans += dis[t]*aug;
    return true;
}

int main()
{
    freopen("sum.in","r",stdin);
    int ncase,x,y,f,c;
    char str[10];
    cin>>ncase;
    while(ncase--)
    {
        scanf("%s%d",str,&x);
        scanf("%d%d%d%d",&n,&m,&s,&t);

        memset(po,0,sizeof(po));
        cl = 1;

        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d%d",&x,&y,&f,&c);
            add(x,y,f,c);
        }

        ans = 0;
        while(spfa());

        cout<<ans<<endl;
    }
    return 0;
}

  

原文地址:https://www.cnblogs.com/yejinru/p/2687636.html