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

[ZJOI2010]网络扩容

时间:2018-03-01 17:28:46      阅读:171      评论:0      收藏:0      [点我收藏+]

标签:span   node   space   color   大致   输入   整数   while   one   

题目描述

给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求: 1、 在不扩容的情况下,1到N的最大流; 2、 将1到N的最大流增加K所需的最小扩容费用。

输入输出格式

输入格式:

 

输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。 接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。

 

输出格式:

 

输出文件一行包含两个整数,分别表示问题1和问题2的答案。

 

输入输出样例

输入样例#1: 
5 8 2
1 2 5 8
2 5 9 9
5 1 6 2
5 1 1 8
1 2 8 7
2 5 4 9
1 2 1 1
1 4 2 1
输出样例#1: 
13 19

说明

30%的数据中,N<=100

100%的数据中,N<=1000,M<=5000,K<=10

给自己加个油,1A。

说一下大致思路。

对于第一问,很简单就是求个最大流F。但是第二问呢?

我们可以这样想,第一问建的边相当于是花费为0,(流量该是多少就是多少)的边

对于有扩容费用的边,就相当于是花费为扩容费用,流量为?的边。

题目中要求将1-n的流量增加k,即限制1-n的最大流为F+k。

那么我们就想办法找一条边来限制F+k这个流量,也就是说其他的边不能够成为限制。

我令S=1,T=n+1,从n到T建一条花费为0,流量为F+k的边。

上文中的?就相当于inf.

那么第二问的答案就是新建图的最大流的情况下的最小费用

代码<?)))><<

技术分享图片
  1 #include<algorithm>
  2 #include<iostream>
  3 #include<cstdio>
  4 #include<cstring>
  5 #include<string>
  6 #include<queue>
  7 #include<cmath>
  8 #define ll long long
  9 #define DB double
 10 #define mod 1000000007
 11 #define inf 147483600
 12 using namespace std;
 13 inline int read()
 14 {
 15     int x=0,w=1;char ch=getchar();
 16     while(ch<0 || ch>9){if(ch==-) w=-1;ch=getchar();}
 17     while(ch>=0 && ch<=9) x=(x<<3)+(x<<1)+ch-0,ch=getchar();
 18     return x*w;
 19 }
 20 const int N=1e6+10;
 21 struct node{
 22     int u,v,c,fl,ne,w;
 23 }e[N],b[N];
 24 int h[N],tot;
 25 void add1(int u,int v,int c,int fl)
 26 {
 27     tot++;e[tot]=(node){u,v,c,fl,h[u],0};h[u]=tot;
 28 }
 29 void add(int u,int v,int c,int fl)
 30 {
 31     add1(u,v,c,fl);add1(v,u,-c,0);
 32 }
 33 deque<int>q;
 34 int d[N],S,T,v[N];
 35 bool bfs()
 36 {
 37     for(int i=S;i<=T;++i)d[i]=inf,v[i]=0;
 38     q.push_back(S);d[S]=0;v[S]=1;
 39     while(!q.empty())
 40     {
 41         int ff=q.front();q.pop_front();v[ff]=0;
 42         for(int i=h[ff];i;i=e[i].ne)
 43         {
 44             int rr=e[i].v;
 45             if(e[i].fl && d[rr]>d[ff]+e[i].c)
 46             {
 47                 d[rr]=d[ff]+e[i].c;
 48                 if(!v[rr])
 49                 {
 50                     v[rr]=1;
 51                     if(q.empty() || d[rr]>=d[q.front()]) q.push_back(rr);
 52                     else q.push_front(rr);
 53                 }
 54             }
 55         }
 56     }
 57     return d[T]!=inf;
 58 }
 59 int dfs(int u,int fl)
 60 {
 61     v[u]=1;
 62     if(u==T || fl==0) return fl;
 63     int get=0,f;
 64     for(int i=h[u];i;i=e[i].ne)
 65     {
 66         int rr=e[i].v;
 67         if(!v[rr] && e[i].fl && d[rr]==d[u]+e[i].c)
 68         {
 69             f=dfs(rr,min(fl,e[i].fl));
 70             if(f==0) continue;
 71             get+=f;fl-=f;
 72             e[i].fl-=f;e[i^1].fl+=f;
 73             if(fl==0) break;
 74         }
 75     }
 76     if(get==0) d[u]=inf;
 77     return get;
 78 } 
 79 int F,D;
 80 int Flow()
 81 {
 82     F=0;D=0;
 83     while(bfs())
 84     {
 85         v[T]=1;
 86         while(v[T])
 87         {
 88             for(int i=S;i<=T;++i) v[i]=0;
 89             int k=dfs(S,inf);
 90             F+=k;D+=d[T]*k; 
 91         }
 92     }
 93 }
 94 int n,m,K;
 95 int main()
 96 {
 97     n=read();m=read();K=read();
 98     tot=1;
 99     for(int i=1;i<=m;++i)
100     {
101         int x,y,z,w;x=read();y=read();z=read();w=read();
102         add(x,y,1,z);
103         b[i]=(node){x,y,0,z,0,w};
104     }
105     S=1;T=n;
106     Flow();printf("%d ",F);K+=F;
107     memset(h,0,sizeof(h));tot=1;
108     S=1;T=n+1;
109     for(int i=1;i<=m;++i)
110     {
111         int u,v,fl,w;
112         u=b[i].u;v=b[i].v;fl=b[i].fl;w=b[i].w;
113         add(u,v,0,fl);add(u,v,w,inf);
114     }
115     add(n,T,0,K);
116     Flow();printf("%d",D);
117     return 0;
118 }
View Code

 

[ZJOI2010]网络扩容

标签:span   node   space   color   大致   输入   整数   while   one   

原文地址:https://www.cnblogs.com/adelalove/p/8488370.html

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