1834: [ZJOI2010]network 网络扩容
Time Limit: 3 SecDescription
给定一张有向图,每条边都有一个容量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
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
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
HINT
Source
【题解】
网络流啊TAT 每次都是数组开小啊
这道题第一问就是直接dinic最大流
第二问就是在做费用流的时候求出的解是满足最大流情况下的解。设第一问的最大流是ANS,要扩容K,有可能在加了新边后最大流大于ANS+K。这样费用可能不是最小的。因此我们可以在1号或N号点新增一条边,容量是K,费用是0。这样就限制了最大流。
1 #include <stdio.h> 2 #include <queue> 3 #include <string.h> 4 using namespace std; 5 const int B=30010; 6 const int INF=2139062143; 7 int next[B], head[B], to[B], flow[B], w[B], c[B], oq[B]; 8 int pre[B], cnt=-1, bi[B], n, m, k, ans=0, d[B]; 9 bool vis[B]; 10 int u[B], v[B], _f[B], _w[B]; 11 queue <int> q; 12 inline void add(int u,int v,int flo,int _w) { 13 cnt++; to[cnt]=v; next[cnt]=head[u]; head[u]=cnt; flow[cnt]=flo; w[cnt]=_w; 14 } 15 inline int min(int a,int b) {return a<b?a:b;} 16 inline void G(int &x) { 17 int y=0, yy=1; char ch=getchar(); 18 while(ch<'0'||ch>'9') { 19 if(ch=='-') yy=-1; 20 ch=getchar(); 21 } 22 while(ch>='0'&&ch<='9') { 23 y=(y<<1)+(y<<3)+ch-'0'; 24 ch=getchar(); 25 } 26 x=y*yy; 27 } 28 inline void qclear() { 29 while(!q.empty()) q.pop(); 30 } 31 inline bool getdfn() { 32 qclear(); 33 memset(c,-1,sizeof(c)); 34 q.push(1); c[1]=1; 35 while(!q.empty()) { 36 int top=q.front(); 37 q.pop(); 38 for (int i=head[top];i>=0;i=next[i]) { 39 int t=to[i]; 40 if(c[t]>=0||flow[i]==0) continue; 41 c[t]=c[top]+1; 42 q.push(t); 43 if(t==n) return 1; 44 } 45 } 46 return 0; 47 } 48 int dinic(int x,int low) { 49 if(x==n) return low; 50 int flo,r=low; 51 for (int i=head[x];i>=0;i=next[i]) { 52 int t=to[i], fl=flow[i]; 53 if(c[t]!=c[x]+1 || fl==0) continue; 54 flo=dinic(t,min(r,fl)); 55 r-=flo; 56 flow[i]-=flo; 57 flow[i^1]+=flo; 58 if(!r) return low; 59 } 60 if(r==low) c[x]=-1; 61 return low-r; 62 } 63 inline bool spfa() { 64 memset(vis,0,sizeof(vis)); 65 memset(oq,0,sizeof(oq)); 66 memset(d,0X7f,sizeof(d)); 67 qclear(); 68 vis[1]=1; d[1]=0; q.push(1); 69 while(!q.empty()) { 70 int top=q.front(); q.pop(); 71 vis[top]=0; oq[top]++; 72 if(oq[top]>n) return 0; 73 for (int i=head[top];i>=0;i=next[i]) { 74 if(flow[i]&&d[top]+w[i]<d[to[i]]) { 75 d[to[i]]=d[top]+w[i]; 76 pre[to[i]]=i; 77 if(!vis[to[i]]) { 78 vis[to[i]]=1; 79 q.push(to[i]); 80 } 81 } 82 } 83 } 84 if(d[n]==INF) return 0; 85 return 1; 86 } 87 inline void mincostflow() { 88 int s=INF; 89 for (int i=pre[n];i>=0;i=pre[to[i^1]]) { 90 s=min(s,flow[i]); 91 if(to[i^1]==1) break; 92 } 93 for (int i=pre[n];i>=0;i=pre[to[i^1]]) { 94 flow[i]-=s; 95 flow[i^1]+=s; 96 ans+=s*w[i]; 97 if(to[i^1]==1) break; 98 } 99 } 100 int main() { 101 G(n), G(m), G(k); 102 memset(head,-1,sizeof(head)); 103 for (int i=1;i<=m;++i) { 104 G(u[i]), G(v[i]), G(_f[i]), G(_w[i]); 105 add(u[i],v[i],_f[i],0); 106 add(v[i],u[i],0,0); 107 } 108 int _flowx=0; 109 while(getdfn()) _flowx += dinic(1,INF); 110 printf("%d ",_flowx); 111 for (int i=1;i<=m;++i) { 112 add(u[i],v[i],INF,_w[i]); 113 add(v[i],u[i],0,-_w[i]); 114 } 115 add(n,n+1,k,0); add(n+1,n,0,0); 116 ++n; 117 while(spfa()) mincostflow(); 118 printf("%d ",ans); 119 return 0; 120 }