P3381 最小费用最大流

  首先用spfa找一条最短路当然这个最短路是按照边的费用算的,在找的过程中,如果这条边的流量已经为0,就一定要放弃这个到达的点,也就是不仅判断dis,也要判断流量·。

  其次,从这条路的结束点(汇点)往它的前驱回溯,找到这个路径上最小的流,每一个流都减去这个最小的流,总流量加上这个最小的流。

  每一个边,都要用它的费用,乘上这个最小流量,加在一起。

  直到不能再找到一条从源点到汇点的完整路径为止。

  记得反向边的费用是负的费用,因为我们要给计算机一个后悔的机会。

  代码如下:

#include<cstdio>
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
#define inf 999999999
#define maxn 500000
struct node
{
    int to,nxt=-1,w,flow,cost;
} edge[maxn];
int head[maxn],pre[maxn],dis[maxn];
bool vis[maxn];
int s,t,n,m,cnt=-1,ans;
void add(int a,int b,int z,int f)
{
    edge[++cnt].to=b;
    edge[cnt].nxt=head[a];
    head[a]=cnt;
    edge[cnt].w=z;
    edge[cnt].cost=f;
}
int spfa()
{
    for(int i=1; i<=n; i++)
    {
        dis[i]=inf;
        vis[i]=0;
        pre[i]=-1;
    }
    queue<int> q;
    dis[s]=0;
    vis[s]=1;
    q.push(s);
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        vis[u]=0;
        for(int i=head[u]; i!=-1; i=edge[i].nxt)
        {
            int to=edge[i].to;
            if(dis[to]>dis[u]+edge[i].cost&&edge[i].w>edge[i].flow)
            {
                dis[to]=dis[u]+edge[i].cost;
                pre[to]=i;
                if(!vis[to])
                {
                    q.push(to);
                    vis[to]=1;
                }
            }
        }
    }
    if(pre[t]!=-1) return 1;
    else return 0;
}
int Mincostmaxflow()
{
    int maxflow=0;
    while(spfa())
    {
        int Min=inf;
        for(int i=pre[t]; i!=-1; i=pre[edge[i^1].to])
            Min=min(Min,edge[i].w-edge[i].flow);
        for(int i=pre[t]; i!=-1; i=pre[edge[i^1].to])
        {
            edge[i].flow+=Min;
            edge[i^1].flow-=Min;
            ans+=Min*edge[i].cost;
        }
        maxflow+=Min;
    }
    return maxflow;
}
int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d%d%d",&n,&m,&s,&t);
    for(int i=1; i<=m; i++)
    {
        int x,y,z,t;
        scanf("%d%d%d%d",&x,&y,&z,&t);
        add(x,y,z,t);
        add(y,x,0,-t);
    }
    printf("%d ",Mincostmaxflow());
    printf("%d",ans);
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/popo-black-cat/p/10294895.html
今日推荐