码迷,mamicode.com
首页 > 其他好文 > 详细

最小费用最大流模板

时间:2017-05-03 15:54:10      阅读:228      评论:0      收藏:0      [点我收藏+]

标签:pop   std   规模   scan   表示   最小   memset   个数   包含   

题目描述

如题,给出一个网络图,以及其源点和汇点,每条边已知其最大流量和单位流量费用,求出其网络最大流和在最大流情况下的最小费用。

输入输出格式

输入格式:

 

第一行包含四个正整数N、M、S、T,分别表示点的个数、有向边的个数、源点序号、汇点序号。

接下来M行每行包含四个正整数ui、vi、wi、fi,表示第i条有向边从ui出发,到达vi,边权为wi(即该边最大流量为wi),单位流量的费用为fi。

 

输出格式:

 

一行,包含两个整数,依次为最大流量和在最大流量情况下的最小费用。

 

输入输出样例

输入样例#1:
4 5 4 3
4 2 30 2
4 3 20 3
2 3 20 1
2 1 30 9
1 3 40 5
输出样例#1:
50 280

说明

时空限制:1000ms,128M

数据规模:

对于30%的数据:N<=10,M<=10

对于70%的数据:N<=1000,M<=1000

对于100%的数据:N<=5000,M<=50000

样例说明:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
using namespace std;
#define INF 9764648
struct bian{
    int to;
    int vol;
    int cost;
    int nex;
}a[100009];
queue<int>q;
int head[5009],pre[5009],path[5009],dis[5009];
int flag[5001];
int n,m,s,t,cnt=1,minn,minf[5009];
int flow=0,mincost=0;
int u,v,f,w;
void into()
{
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d%d",&u,&v,&f,&w);    
        a[++cnt].to=v; a[cnt].vol=f; a[cnt].cost=w; a[cnt].nex=head[u]; head[u]=cnt;
        a[++cnt].to=u; a[cnt].vol=0; a[cnt].cost=-w; a[cnt].nex=head[v]; head[v]=cnt;
    }
}
bool spfa( )
{
    memset(pre,-1,sizeof(pre));
    memset(dis,127,sizeof(dis));    
    memset(flag,0,sizeof(f));
    while(!q.empty())
        q.pop();    
    q.push(s);
    dis[s]=0;
    pre[s]=0;
    flag[s]=1;
    minf[s]=INF;
    int tot=0;minn=INF;
    while( ! q.empty() )
    {    
        
        int u=q.front();
        flag[u]=0;
        q.pop();
        for(int e=head[u] ; e ; e=a[e].nex )
        {
            int v=a[e].to;
            if(a[e].vol>0&&dis[u]+a[e].cost<dis[v])
            {                
                pre[v]=u;
                dis[v]=dis[u]+a[e].cost;
                path[v]=e;
                minf[v]=min(minf[u],a[e].vol);       
                if(!flag[v])    flag[v]=1,q.push(v);   判断加在里边      
            }
        }
    }
    if(dis[t]>=INF)    return false;
     return true;
}
void minflow()
{    
    while(spfa())
    {
        int f=minf[t];        
        flow+=f;
        mincost+=f*dis[t];
        int k=t;
        while(k!=s)
         {
             a[path[k]].vol-=f;
             a[path[k]^1].vol +=f;
             k=pre[k];
         } 
    }    
}
int main()
{
    scanf("%d%d%d%d",&n,&m,&s,&t);    
    into();
    minflow();
    cout<<flow<< <<mincost;
    return 0;
}

 

如图,最优方案如下:

第一条流为4-->3,流量为20,费用为3*20=60。

第二条流为4-->2-->3,流量为20,费用为(2+1)*20=60。

第三条流为4-->2-->1-->3,流量为10,费用为(2+9+5)*10=160。

故最大流量为50,在此状况下最小费用为60+60+160=280。

故输出50 280。

出错较多,

  *链表从2开始存比较适合(便于找对边,不会丢数据)

  *广搜可能重复找到一个点不能以是否入队判断

 

最小费用最大流模板

标签:pop   std   规模   scan   表示   最小   memset   个数   包含   

原文地址:http://www.cnblogs.com/CLGYPYJ/p/6802212.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!