首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >P3381 【模板】最小费用最大流

P3381 【模板】最小费用最大流

作者头像
attack
发布2018-04-12 11:53:24
8020
发布2018-04-12 11:53:24
举报

题目描述

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

输入输出格式

输入格式:

第一行包含四个正整数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

(BYX:最后两个点改成了1200ms)

数据规模:

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

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

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

样例说明:

如图,最优方案如下:

第一条流为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。

SPFA费用流的模板题,

用SPFA检查是否可以增广

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cmath>
  5 #include<queue>
  6 using namespace std;
  7 const int MAXN=2000001;
  8 const int maxn=0x7fffffff;
  9 void read(int &n)
 10 {
 11     char c='+';int x=0;bool flag=0;
 12     while(c<'0'||c>'9'){c=getchar();if(c=='-')flag=1;}
 13     while(c>='0'&&c<='9'){x=x*10+(c-48);c=getchar();}
 14     flag==1?n=-x:n=x;
 15 }
 16 struct node
 17 {
 18     int u,v,flow,spend,nxt;
 19 }edge[MAXN];
 20 int head[MAXN];
 21 int num=0;
 22 int n,m,s,t;
 23 int ans=0,maxflow=0;
 24 int dis[MAXN];
 25 int vis[MAXN];
 26 int from[MAXN];
 27 void add_edge(int x,int y,int z,int c)
 28 {
 29     edge[num].u=x;
 30     edge[num].v=y;
 31     edge[num].flow=z;
 32     edge[num].spend=c;
 33     edge[num].nxt=head[x];
 34     head[x]=num++;
 35 }
 36 bool SPFA()
 37 {
 38     for(int i=1;i<=n;i++)
 39         dis[i]=maxn;
 40     memset(vis,0,sizeof(vis));
 41     dis[s]=0;
 42     queue<int>q;
 43     q.push(s);
 44     vis[s]=1;
 45     while(q.size()!=0)
 46     {
 47         int p=q.front();
 48         q.pop();
 49         vis[p]=0;
 50         for(int i=head[p];i!=-1;i=edge[i].nxt)
 51         {
 52             if(dis[edge[i].v]>dis[edge[i].u]+edge[i].spend&&edge[i].flow>0)
 53             {
 54                 dis[edge[i].v]=dis[edge[i].u]+edge[i].spend;
 55                 from[edge[i].v]=i;
 56                 if(!vis[edge[i].v])
 57                 {
 58                     vis[edge[i].v]=1;
 59                     q.push(edge[i].v);
 60                 }
 61             }
 62         }
 63     }
 64     if(dis[t]!=maxn)
 65         return 1;
 66     else 
 67         return 0;
 68     
 69 }
 70 void f()
 71 {
 72     int mn=maxn;
 73     for(int i=t;i!=s;i=edge[from[i]].u)
 74         mn=min(mn,edge[from[i]].flow);
 75     for(int i=t;i!=s;i=edge[from[i]].u)
 76     {
 77         edge[from[i]].flow-=mn;
 78         edge[from[i]^1].flow+=mn;
 79         ans+=(mn*edge[from[i]].spend);
 80     }
 81     maxflow+=mn;
 82 }
 83 int main()
 84 {
 85     read(n);read(m);read(s);read(t);
 86     //s=1;
 87     //t=n;
 88     memset(head,-1,sizeof(head));
 89     for(int i=1;i<=m;i++)
 90     {
 91         int x,y,z,c;
 92         read(x);read(y);read(z);read(c);
 93         add_edge(x,y,z,c);
 94         add_edge(y,x,0,-c);
 95     }
 96     while(SPFA())
 97         f();
 98     printf("%d %d",maxflow,ans);
 99     return 0;
100 }
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2017-07-28 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 题目描述
  • 输入输出格式
  • 输入输出样例
  • 说明
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档