【BZOJ 1834】 [ZJOI2010]network 网络扩容

Description

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

Input

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

Output

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

Sample Input

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

Sample Output

13 19
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
 
第一问最大流
第二问
建立超级源和超级汇,超级源向1连边,容量为K,n向超级汇连边,容量同上。原来的每条边再建立一条,容量为inf,费用为W,在原图上增广,跑最小费用最大流
但是!!!新边一定要在求完第一问之后再建。。。
代码量略大。。。不过我都上套板子。。。
  1 #include<cstdio>
  2 #include<cstring>
  3 #include<cmath>
  4 #include<iostream>
  5 using namespace std;
  6 const int N=55555,inf=1000000;
  7 struct ee{int to,next,f,w;}e[N*2];
  8 int S,T,cnt=1,n,k,ans1,ans2,timer,m,u[N],v[N],w[N],c[N],mid;
  9 int head[N],dis[N],pre[N],q[N];
 10 bool inq[N],flag=1;
 11 void ins(int u,int v,int f,int w){
 12     e[++cnt].to=v,e[cnt].next=head[u],e[cnt].f=f,e[cnt].w=w,head[u]=cnt;
 13     e[++cnt].to=u,e[cnt].next=head[v],e[cnt].f=0,e[cnt].w=-w,head[v]=cnt;
 14 }
 15 bool spfa(){
 16     for (int i=1;i<=T;i++) dis[i]=inf;
 17     int h=0,t=1;
 18     q[t]=S;dis[S]=0;inq[S]=1;
 19     while (h!=t){
 20         int now=q[++h];if(h==2501) h=0;
 21         for (int i=head[now];i;i=e[i].next){
 22             int v=e[i].to;
 23             if (dis[v]>dis[now]+e[i].w&&e[i].f){
 24                 dis[v]=dis[now]+e[i].w;
 25                 pre[v]=i;
 26                 if (!inq[v]){
 27                     q[++t]=v;if (t==2501) t=0;
 28                     inq[v]=1;
 29                 }
 30             }
 31         }
 32         inq[now]=0;
 33     }
 34     if (dis[T]==inf) return 0;
 35     return 1;
 36 }
 37   
 38 void updata(){
 39     int tmp=T,flow=inf;
 40     while (tmp!=S){
 41         int l=pre[tmp],v=e[l].to;
 42         flow=min(flow,e[l].f);
 43         tmp=e[l^1].to;
 44     }
 45     tmp=T;
 46     while (tmp!=S){
 47         int l=pre[tmp],v=e[l].to;
 48         e[l].f-=flow;e[l^1].f+=flow;
 49         tmp=e[l^1].to;
 50     }
 51     mid+=flow;
 52     if(mid>=k) flag=0;
 53     ans2+=dis[T]*flow;
 54 }
 55  
 56 bool bfs(){
 57     for (int i=1;i<=T;i++) dis[i]=inf;
 58     int h=0,t=1,now;
 59     q[1]=1;dis[1]=0;
 60     while(h!=t){
 61         now=q[++h];
 62         for (int i=head[now];i;i=e[i].next){
 63             int v=e[i].to;
 64             if (e[i].f&&dis[now]+1<dis[v]){
 65                 dis[v]=dis[now]+1;
 66                 if (v==n)return 1;
 67                 q[++t]=v;
 68             }
 69         }
 70     }
 71     if (dis[n]==inf) return 0; return 1;
 72 }
 73   
 74 int dinic(int now,int f){
 75     if (now==n) return f;
 76     int rest=f;
 77     for (int i=head[now];i;i=e[i].next){
 78         int v=e[i].to;
 79         if (e[i].f&&dis[v]==dis[now]+1&&rest){
 80             int t=dinic(v,min(rest,e[i].f));
 81             if (!t) dis[v]=0;
 82             e[i].f-=t;
 83             e[i^1].f+=t;
 84             rest-=t;
 85             //if(t) printf("%d %d %d\n",now,v,e[i].f);
 86         }
 87     }
 88     return f-rest;
 89 }
 90  
 91 int main(){
 92     scanf("%d%d%d",&n,&m,&k);
 93     S=0,T=n+1;
 94     for (int i=1;i<=m;i++){
 95         scanf("%d%d%d%d",&u[i],&v[i],&c[i],&w[i]);
 96         ins(u[i],v[i],c[i],0);
 97     }
 98     ins(S,1,k,0);ins(n,T,k,0);
 99     while(bfs()) 
100     ans1+=dinic(1,inf);
101     for (int i=1;i<=m;i++)ins(u[i],v[i],inf,w[i]);
102     while(flag&&spfa()) 
103     updata();
104     printf("%d %d",ans1,ans2);
105 }

 

你可能感兴趣的:(【BZOJ 1834】 [ZJOI2010]network 网络扩容)