C++之路进阶——网络流(网络扩容)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++之路进阶——网络流(网络扩容)相关的知识,希望对你有一定的参考价值。
1362 网络扩容
省队选拔赛
时间限制: 2 s
空间限制: 128000 KB
题目等级 : 大师 Master
题目描述 Description
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。求:
1、 在不扩容的情况下,1到N的最大流;
2、 将1到N的最大流增加K所需的最小扩容费用。
输入描述 Input Description
输入文件的第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。
接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
输出描述 Output Description
输出文件一行包含两个整数,分别表示问题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
数据范围及提示 Data Size & Hint
30%的数据中,N<=100
100%的数据中,N<=1000,M<=5000,K<=10
题解:
在最大流的参与网络上加新边跑最小费用最大流!
代码:
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<queue> 5 #define maxn 10010 6 #define inf 0x7fffffff 7 #define S 1 8 #define T n 9 10 using namespace std; 11 12 int n,m,K,cnt=1,vw[maxn],ans1,ans2,U[maxn],V[maxn],head[maxn],x,dis[maxn],inq[maxn],from[maxn]; 13 14 struct ss 15 { 16 int to; 17 int next; 18 int c; 19 int w; 20 int from; 21 }e[100010]; 22 23 void add(int u,int v,int c,int w) 24 { 25 e[++cnt].to=v; 26 e[cnt].next=head[u]; 27 e[cnt].from=u; 28 e[cnt].c=c; 29 e[cnt].w=w; 30 head[u]=cnt; 31 } 32 33 void insert(int u,int v,int c,int w) 34 { 35 add(u,v,c,w); 36 add(v,u,0,-w); 37 } 38 39 bool bfs() 40 { 41 for (int i=1;i<=T;i++) dis[i]=inf; 42 queue<int> que; 43 que.push(S); 44 dis[S]=0; 45 while (!que.empty()) 46 { 47 int now=que.front(); 48 que.pop(); 49 for (int i=head[now];i;i=e[i].next) 50 if (e[i].c&&dis[e[i].to]>dis[now]+1) 51 { 52 dis[e[i].to]=dis[now]+1; 53 que.push(e[i].to); 54 if (e[i].to==T) return 1; 55 } 56 } 57 return 0; 58 } 59 60 int dinic(int x,int INF) 61 { 62 if (x==T) return INF; 63 int rest=INF; 64 for (int i=head[x];i;i=e[i].next) 65 if (e[i].c&&dis[e[i].to]==dis[x]+1) 66 { 67 int now=dinic(e[i].to,min(rest,e[i].c)); 68 e[i].c-=now; 69 if (!now) dis[now]=0; 70 e[i^1].c+=now; 71 rest-=now; 72 } 73 return INF-rest; 74 } 75 76 bool spfa() 77 { 78 for (int i=0;i<=T;i++) dis[i]=inf; 79 queue<int> que; 80 que.push(0); 81 inq[0]=1; 82 dis[0]=0; 83 while (!que.empty()) 84 { 85 int now=que.front(); 86 que.pop(); 87 inq[now]=0; 88 for (int i=head[now];i;i=e[i].next) 89 if (e[i].c&&dis[e[i].to]>dis[now]+e[i].w) 90 { 91 dis[e[i].to]=dis[now]+e[i].w; 92 from[e[i].to]=i; 93 if (!inq[e[i].to]) 94 { 95 inq[e[i].to]=1; 96 que.push(e[i].to); 97 } 98 } 99 } 100 if (dis[T]==inf) return 0; 101 else return 1; 102 } 103 104 int bcf() 105 { 106 int x=inf; 107 for (int i=from[T];i;i=from[e[i].from]) 108 x=min(x,e[i].c); 109 for (int i=from[T];i;i=from[e[i].from]) 110 { 111 ans2+=x*e[i].w; 112 e[i].c-=x; 113 e[i^1].c+=x; 114 } 115 } 116 117 int main() 118 { 119 scanf("%d%d%d",&n,&m,&K); 120 for (int i=1;i<=m;i++) 121 { 122 int u,v,w,c; 123 scanf("%d%d%d%d",&U[i],&V[i],&c,&vw[i]); 124 insert(U[i],V[i],c,0); 125 } 126 while (bfs()) 127 while (x=dinic(S,inf)) ans1+=x; 128 insert(0,1,K,0); 129 printf("%d ",ans1); 130 for (int i=1;i<=m;i++) 131 insert(U[i],V[i],K,vw[i]); 132 while(spfa()) bcf(); 133 printf("%d\n",ans2); 134 return 0; 135 }
以上是关于C++之路进阶——网络流(网络扩容)的主要内容,如果未能解决你的问题,请参考以下文章
[ZJOI2010][bzoj1834] 网络扩容 [费用流]