1834: [ZJOI2010]network 网络扩容
Time Limit: 3 Sec Memory Limit: 64 MBDescription
给定一张有向图,每条边都有一个容量C和一个扩容费用W。这里扩容费用是指将容量扩大1所需的费用。
求:
1、在不扩容的情况下,1到N的最大流;
2、将1到N的最大流增加K所需的最小扩容费用。
Input
第一行包含三个整数N,M,K,表示有向图的点数、边数以及所需要增加的流量。
接下来的M行每行包含四个整数u,v,C,W,表示一条从u到v,容量为C,扩容费用为W的边。
N<=1000,M<=5000,K<=10
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
先跑出最大流,然后在残量网络上加边,每条边的费用为 c, 限制 n 到汇点的流量为k
跑费用流,流量流过一次就代表要进行扩容
跑出的费用就是答案
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <algorithm> 5 #include <queue> 6 #define LL long long 7 8 using namespace std; 9 10 const int MAXM = 1e5 + 10; 11 const int MAXN = 2e3 + 10; 12 13 queue<int> q; 14 int S, T; 15 int N, M, K; 16 LL u, v, c, w; 17 const LL inf = 1e9; 18 LL maxflow = 0; 19 LL sum = 0; 20 int cnt = 0; 21 int pre[MAXN]; 22 int flag[MAXN]; 23 int dis[MAXN]; 24 int e[MAXN]; 25 int h[MAXN]; 26 int head[MAXN]; 27 struct edge { 28 int u, v; 29 LL w; 30 LL c; 31 int next; 32 } g[5 * MAXM], ed[2 * MAXM]; 33 34 inline LL read() 35 { 36 LL x = 0, w = 1; char ch = 0; 37 while(ch < '0' || ch > '9') { 38 if(ch == '-') { 39 w = -1; 40 } 41 ch = getchar(); 42 } 43 while(ch >= '0' && ch <= '9') { 44 x = x * 10 + ch - '0'; 45 ch = getchar(); 46 } 47 return x * w; 48 } 49 50 void addedge(int u, int v, LL w, LL c) 51 { 52 g[cnt].v = v; 53 g[cnt].w = w; 54 g[cnt].c = c; 55 g[cnt].next = head[u]; 56 head[u] = cnt++; 57 } 58 59 bool BFS() 60 { 61 memset(h, -1, sizeof h); 62 h[S] = 0; 63 q.push(S); 64 while(!q.empty()) { 65 int t = q.front(); 66 q.pop(); 67 for(int j = head[t]; j != -1; j = g[j].next) { 68 int to = g[j].v; 69 if(h[to] == -1 && g[j].w) { 70 h[to] = h[t] + 1; 71 q.push(to); 72 } 73 } 74 } 75 return h[T] != -1; 76 } 77 78 LL DFS(int x, LL f) 79 { 80 LL used = 0; 81 if(x == T) { 82 return f; 83 } 84 for(int j = head[x]; j != -1; j = g[j].next) { 85 int to = g[j].v; 86 if(h[to] == h[x] + 1 && g[j].w) { 87 LL w = f - used; 88 w = DFS(to, min(w, g[j].w)); 89 g[j].w -= w, g[j ^ 1].w += w; 90 used += w; 91 if(used == f) { 92 break; 93 } 94 } 95 } 96 if(used == 0) { 97 h[x] = -1; 98 } 99 return used; 100 } 101 102 void dinic() 103 { 104 while(BFS()) { 105 maxflow += DFS(S, inf); 106 } 107 } 108 109 bool SPFA() 110 { 111 memset(pre, -1, sizeof pre); 112 memset(flag, 0, sizeof flag); 113 memset(dis, -1, sizeof dis); 114 dis[S] = 0; 115 q.push(S); 116 while(!q.empty()) { 117 int t = q.front(); 118 q.pop(); 119 flag[t] = 0; 120 for(int j = head[t]; j != -1; j = g[j].next) { 121 int to = g[j].v; 122 if(g[j].w && (dis[to] == -1 || dis[to] > (dis[t] + g[j].c))) { 123 dis[to] = dis[t] + g[j].c; 124 e[to] = j; 125 pre[to] = t; 126 if(!flag[to]) { 127 flag[to] = 1; 128 q.push(to); 129 } 130 } 131 } 132 } 133 if(pre[T] == -1) { 134 return false; 135 } 136 LL maxflow = 1e18; 137 for(int j = T; pre[j] != -1; j = pre[j]) { 138 maxflow = min(g[e[j]].w, maxflow); 139 } 140 for(int j = T; pre[j] != -1; j = pre[j]) { 141 g[e[j]].w -= maxflow, g[e[j] ^ 1].w += maxflow; 142 } 143 sum += maxflow * dis[T]; 144 } 145 146 int main() 147 { 148 memset(head, -1, sizeof head); 149 N = read(), M = read(), K = read(); 150 S = 0, T = N + 1; 151 for(int i = 1; i <= M; i++) { 152 u = read(), v = read(), w = read(), c = read(); 153 addedge(u, v, w, 0); 154 addedge(v, u, 0, 0); 155 ed[i].u = u, ed[i].v = v, ed[i].w = w, ed[i].c = c; 156 } 157 addedge(S, 1, inf, 0); 158 addedge(1, S, 0, 0); 159 addedge(N, T, inf, 0); 160 addedge(T, N, 0, 0); 161 dinic(); 162 printf("%lld ", maxflow); 163 for(int i = 1; i <= M; i++) { 164 addedge(ed[i].u, ed[i].v, K, ed[i].c); 165 addedge(ed[i].v, ed[i].u, 0, -ed[i].c); 166 } 167 g[2 * M].w = K; 168 g[2 * M + 1].w = 0; 169 while(SPFA()) { 170 } 171 printf("%lld ", sum); 172 return 0; 173 } 174 175 176 /* 177 5 8 2 178 1 2 5 8 179 2 5 9 9 180 5 1 6 2 181 5 1 1 8 182 1 2 8 7 183 2 5 4 9 184 1 2 1 1 185 1 4 2 1 186 187 */