Drainage Ditches
Hal Burch
Every time it rains on Farmer John's fields, a pond forms over Bessie's favorite clover patch. This means that the clover is covered by water for awhile and takes quite a long time to regrow. Thus, Farmer John has built a set of drainage ditches so that Bessie's clover patch is never covered in water. Instead, the water is drained to a nearby stream. Being an ace engineer, Farmer John has also installed regulators at the beginning of each ditch, so he can control at what rate water flows into that ditch.
Farmer John knows not only how many gallons of water each ditch can transport per minute but also the exact layout of the ditches, which feed out of the pond and into each other and stream in a potentially complex network. Note however, that there can be more than one ditch between two intersections.
Given all this information, determine the maximum rate at which water can be transported out of the pond and into the stream. For any given ditch, water flows in only one direction, but there might be a way that water can flow in a circle.
PROGRAM NAME: ditch
INPUT FORMAT
Line 1:
Two space-separated integers, N (0 <= N <= 200) and M (2 <= M <= 200). N is the number of ditches that Farmer John has dug. M is the number of intersections points for those ditches. Intersection 1 is the pond. Intersection point M is the stream.
Line 2..N+1:
Each of N lines contains three integers, Si, Ei, and Ci. Si and Ei (1 <= Si, Ei <= M) designate the intersections between which this ditch flows. Water will flow through this ditch from Si to Ei. Ci (0 <= Ci <= 10,000,000) is the maximum rate at which water will flow through the ditch.
SAMPLE INPUT (file ditch.in)
5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10
OUTPUT FORMAT
One line with a single integer, the maximum rate at which water may emptied from the pond.
SAMPLE OUTPUT (file ditch.out)
50
最基本的网络流
1: #include<iostream>
2: #include<fstream>
3: #include<string>
4: #include<vector>
5: #include<map>
6: #include<algorithm>
7: #include<sstream>
8: #include <cstring>
9: #include <queue>
10: using namespace std;
11: const int MAXN = 220;
12: const int infi = 0x7FFFFFFF;
13: int capacity[MAXN][MAXN], prenode[MAXN], flow[MAXN];
14: queue<int> mq;
15:
16: int start, end, N;
17: void init(){
18: freopen("ditch.in","r",stdin);
19: //freopen("e:\\usaco\\ditch.in","r",stdin);
20: start = 1;
21: scanf("%d %d",&N,&end); int c, s, t;
22: memset(capacity,0,sizeof(capacity));
23: for(int i=0;i<N;i++)
24: {
25: scanf("%d %d %d",&c,&s,&t);
26: capacity[c][s] += t; //两个节点间不只有一条路
27: }
28: }
29: int bfs(){//寻找增广路径
30: while(!mq.empty()) mq.pop();
31: mq.push(start); //源节点入队
32: //memset(flow,0,sizeof(flow));
33: memset(prenode,-1,sizeof(prenode)); //重置前向节点
34: prenode[start] = 0; flow[start]=infi; //源节点流量无限大
35: while(!mq.empty()){
36: int cur = mq.front();
37: mq.pop();
38: if(cur == end) break; //到达汇点结束路径
39: for(int i=1;i<=end;i++){
40: if(prenode[i]==-1 && capacity[cur][i]) //访问当前节点所有未访问的相邻节点,更新flow
41: {
42: prenode[i] = cur;
43: flow[i] = (flow[cur]<capacity[cur][i]?flow[cur]:capacity[cur][i]);
44: mq.push(i);
45: }
46: }
47: }
48: if(prenode[end]==-1) //如果未找到增广路径返回-1
49: return -1;
50: return flow[end];
51: }
52: int Edmonds_Karp(){
53: int total = 0, pathcapacity;//pathcapacity 路径增加量
54: while((pathcapacity = bfs()) != -1){//可以找到增广路径时候进行循环
55: int cur = end; //从汇点开始增加逆向节点
56: while( cur != start ){
57: int t = prenode[cur] ;
58: capacity[t][cur] -= pathcapacity;
59: capacity[cur][t] += pathcapacity;
60: cur = t;
61: }
62: total += pathcapacity;//max_flow
63: }
64: return total;
65: }
66: void output(){
67: freopen("ditch.out","w",stdout);
68: //freopen("c:\\usaco\\ditch.out","w",stdout);
69: cout<<Edmonds_Karp()<<endl;
70: }
71: int main()
72: {
73: init();
74: output();
75: return 0;
76: }
标程:使用贪心法,寻找一条增广路径的时候不断寻找cap最大的,未被访问的节点mloc;然后更新跟mloc相邻的节点flow以
及prenode信息.最后当运行到end时候,更新路径节点capacity,同时增加max_flow.重复上述过程直到找不到增广路径
1: #include <stdio.h>
2: #include <string.h>
3:
4: #define MAXI 200
5:
6: /* total drain amount between intersection points */
7: int drain[MAXI][MAXI];
8: int nint; /* number of intersection points */
9:
10: int cap[MAXI]; /* amount of flow that can get to each node */
11: int vis[MAXI]; /* has this node been visited by Dijkstra's yet? */
12: int src[MAXI]; /* the previous node on the path from the source to here */
13:
14: int augment(void)
15: { /* run a Dijkstra's varient to find maximum augmenting path */
16: int lv;
17: int mloc, max;
18: int t;
19:
20: memset(cap, 0, sizeof(cap));
21: memset(vis, 0, sizeof(vis));
22:
23: cap[0] = 2000000000;
24: while (1)
25: {
26: /* find maximum unvisited node */
27: max = 0;
28: mloc = -1;
29: for (lv = 0; lv < nint; lv++)
30: if (!vis[lv] && cap[lv] > max)
31: {
32: max = cap[lv];
33: mloc = lv;
34: }
35: if (mloc == -1) return 0;
36: if (mloc == nint-1) break; /* max is the goal, we're done */
37:
38: vis[mloc] = -1; /* mark as visited */
39:
40: /* update neighbors, if going through this node improves the
41: capacity */
42: for (lv = 0; lv < nint; lv++)
43: if (drain[mloc][lv] > cap[lv] && max > cap[lv])
44: {
45: cap[lv] = drain[mloc][lv];
46: if (cap[lv] > max) cap[lv] = max;
47: src[lv] = mloc;
48: }
49: }
50: max = cap[nint-1];
51:
52: /* augment path, starting at end */
53: for (lv = nint-1; lv > 0; lv = src[lv])
54: {
55: t = src[lv];
56: drain[t][lv] -= max;
57: drain[lv][t] += max;
58: }
59: return max;
60: }
61:
62: int main(int argc, char **argv)
63: {
64: FILE *fout, *fin;
65: int lv;
66: int num;
67: int p1, p2, c;
68:
69: if ((fin = fopen("ditch.in", "r")) == NULL)
70: {
71: perror ("fopen fin");
72: exit(1);
73: }
74: if ((fout = fopen("ditch.out", "w")) == NULL)
75: {
76: perror ("fopen fout");
77: exit(1);
78: }
79:
80: fscanf (fin, "%d %d", &num, &nint);
81: while (num--)
82: {
83: fscanf (fin, "%d %d %d", &p1, &p2, &c);
84: p1--;
85: p2--;
86: drain[p1][p2] += c; /* note += handles two ditches between same points */
87: }
88:
89: /* max flow algorithm: augment while you can */
90: c = 0;
91: while ((p1 = augment()))
92: c += p1;
93: fprintf (fout, "%d\n", c);
94: return 0;
95: }