POJ 1273Drainage Ditches(入门网络流模板)
Drainage Ditches
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions: 83222 | Accepted: 32330 |
Description
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.
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.
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.
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.
Input
The input includes several cases.
For each case, the first line contains 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. Each of the following 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.
Output
For each case, output a single integer, the maximum rate at which water may emptied from the pond.
Sample Input
5 4 1 2 40 1 4 20 2 4 20 2 3 30 3 4 10
Sample Output
50
每次在农夫约翰的田地上下雨时,一个池塘就形成了贝西最喜欢的三叶草补丁。这意味着三叶草被水覆盖了一段时间,需要相当长的时间才能再生。因此,农夫约翰已经建立了一套排水沟,
以便贝西的三叶草补丁不会被水覆盖。相反,水被排放到附近的小溪。作为一名高级工程师,John Farmer在每条沟的开始都安装了调节器,因此他可以控制水流入该沟的速率。
农夫约翰不仅知道每个沟渠每分钟可以运输多少加仑水,而且还知道沟渠的确切布局,这些沟渠从池塘中流出,流入彼此,流入一个潜在的复杂网络。
根据所有这些信息,确定水可以从池塘运输到河流的最大速率。对于任何给定的沟渠,水只在一个方向上流动,但可能有一种方式,水可以在一个圆圈中流动。
输入
输入包括几种情况。对于每种情况,第一行包含两个空格分隔的整数N(0 <= N <= 200)和M(2 <= M <= 200)。 N是农夫约翰挖的沟渠数量。 M是这些沟渠的交点数。
十字路口是池塘。交点M是流。以下N行中的每一行都包含三个整数Si,Ei和Ci。 Si和Ei(1 <= Si,Ei <= M)表示沟渠流动的交点。水将通过这条沟渠从Si流向Ei。
Ci(0 <= Ci <= 10,000,000)是水流过沟渠的最大速率。
产量
对于每种情况,输出一个整数,即池中水可能排空的最大速率。
Edmonds_Karp算法
#include<iostream> #include<string> #include<cstdio> #include<queue> #include<vector> #include<algorithm> #define LL long long #define inf 1<<29 #define s(a) scanf("%d",&a) #define CL(a,b) memset(a,b,sizeof(a)) using namespace std; const int N=205; int n,m,u,v,cost; int Map[N][N],path[N],flow[N]; int start,endd; queue<int>q; int bfs() { while(!q.empty()) q.pop(); CL(path,-1); path[start]=0,flow[start]=inf; // 起始容量为inf; q.push(start); while(!q.empty()){ int t=q.front(); q.pop(); if(t==endd) break; for(int i=1;i<=m;i++){ // 遍历可走路径; if(i!=start&&path[i]==-1&&Map[t][i]){ // 符合这三种情况表示该路径可走; flow[i]=flow[t]<Map[t][i]?flow[t]:Map[t][i]; q.push(i); path[i]=t; } } } if(path[endd]==-1) return -1; // 说明没有找到可走路径,返回-1; return flow[endd]; // 找到一条路径之后的增流量; } int Edmonds_Karp() { int max_flow=0,step,now,pre; while((step=bfs())!=-1){ // 找不到路径之后便退出; max_flow+=step; // 累加流量; now=endd; while(now!=start){ // 将找到的路径进行反向处理,并更新实际容量; pre=path[now]; Map[pre][now]-=step; // 更新正向边的实际容量; Map[now][pre]+=step; // 添加反向边; now=pre; } } return max_flow; } int main() { while(~scanf("%d%d",&n,&m)){ CL(Map,0); for(int i=0;i<n;i++){ scanf("%d%d%d",&u,&v,&cost); Map[u][v]+=cost; // 为防止一条边不止一次输入; } start=1,endd=m; printf("%d\n",Edmonds_Karp()); } return 0; }
DINIC 算法
#include <cstdio> #include <string.h> #include <queue> using namespace std; int const inf = 0x3f3f3f3f; int const MAX = 205; int n, m; int c[MAX][MAX], dep[MAX];//dep[MAX]代表当前层数 int bfs(int s, int t)//重新建图,按层次建图 { queue<int> q; while(!q.empty()) q.pop(); memset(dep, -1, sizeof(dep)); dep[s] = 0; q.push(s); while(!q.empty()){ int u = q.front(); q.pop(); for(int v = 1; v <= m; v++){ if(c[u][v] > 0 && dep[v] == -1){//如果可以到达且还没有访问,可以到达的条件是剩余容量大于0,没有访问的条件是当前层数还未知 dep[v] = dep[u] + 1; q.push(v); } } } return dep[t] != -1; } int dfs(int u, int mi, int t)//查找路径上的最小流量 { if(u == t) return mi; int tmp; for(int v = 1; v <= m; v++){ if(c[u][v] > 0 && dep[v] == dep[u] + 1 && (tmp = dfs(v, min(mi, c[u][v]), t))){ c[u][v] -= tmp; c[v][u] += tmp; return tmp; } } return 0; } int dinic() { int ans = 0, tmp; while(bfs(1, m)){ while(1){ tmp = dfs(1, inf, m); if(tmp == 0) break; ans += tmp; } } return ans; } int main() { while(~scanf("%d %d", &n, &m)){ memset(c, 0, sizeof(c)); int u, v, w; while(n--){ scanf("%d %d %d", &u, &v, &w); c[u][v] += w; } printf("%d\n", dinic()); } return 0; }