最小费用流

/*



题目:

    求最小费用最大流的裸模板



分析:

    每次找到一条最短路,然后记录下每个经过的节点的前驱结点,然后若能够

    到达终点的话,从终点开始往回找到最小流,然后再从终点往回依次更改当

    前每条边的流量以及反向弧,直到不能再找到一条最短路为止,找最短路的

    算法是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;

}

  

你可能感兴趣的:(流)