http://poj.org/problem?id=1273
Drainage Ditches
Time Limit: 1000MS | Memory Limit: 10000K | |
Total Submissions:87219 | Accepted: 33916 |
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
現在有m個池塘(從1到m開始編號,1為源點,m為匯點),及n條水渠,給出這n條水渠所連接的池塘和所能流過的水量,求水渠中所能流過的水的最大容量.一道基礎的最大流題目。
——其他練習題 POJ3436 、

1 #include <cstdio> 2 #include <cstdlib> 3 #include <cstring> 4 #include <bitset> 5 #include <cmath> 6 #include <cctype> 7 #include <iostream> 8 #include <algorithm> 9 #include <string> 10 #include <vector> 11 #include <queue> 12 #include <map> 13 #include <set> 14 #include <sstream> 15 #include <iomanip> 16 using namespace std; 17 typedef long long ll; 18 typedef unsigned long long ull; 19 const ll inff = 0x3f3f3f3f3f3f3f3f; 20 #define FOR(i,a,b) for(int i(a);i<=(b);++i) 21 #define FOL(i,a,b) for(int i(a);i>=(b);--i) 22 #define REW(a,b) memset(a,b,sizeof(a)) 23 #define inf int(0x3f3f3f3f) 24 #define si(a) scanf("%d",&a) 25 #define sl(a) scanf("%I64d",&a) 26 #define sd(a) scanf("%lf",&a) 27 #define ss(a) scanf("%s",a) 28 #define mod ll(998244353) 29 #define pb push_back 30 #define eps 1e-6 31 #define lc d<<1 32 #define rc d<<1|1 33 #define Pll pair<ll,ll> 34 #define P pair<int,int> 35 #define pi acos(-1) 36 const int N=100008,M=100008; 37 int head[N],tot,n,m,a,b,c; 38 struct node{ 39 int next,c,to;}e[M]; 40 struct max_flow{ 41 int S,T,n; 42 int lev[N],q[N],cur[N],f; 43 void init(int _s,int _t) 44 { 45 tot=0;S=_s,T=_t,n=T+1; 46 FOR(i,0,n) head[i]=-1; 47 } 48 void add(int a,int b,int c) 49 { 50 e[tot].next=head[a]; 51 e[tot].to=b; 52 e[tot].c=c; 53 head[a]=tot++; 54 } 55 void Add(int a,int b,int c) 56 { 57 add(a,b,c); 58 add(b,a,0); 59 } 60 int bfs() 61 { 62 FOR(i,0,n) lev[i]=0; 63 lev[S]=1,f=0,q[f++]=S; 64 FOR(i,0,f-1) 65 { 66 int u=q[i]; 67 for(int i=head[u];i!=-1;i=e[i].next) 68 if(lev[e[i].to]==0&&e[i].c>0) 69 { 70 int to=e[i].to; 71 lev[to]=lev[u]+1; 72 q[f++]=to; 73 if(to==T) return 1; 74 } 75 } 76 return 0; 77 } 78 int dfs(int u,int f) 79 { 80 if(u==T) return f; 81 int tag=0,c; 82 for(int &i=cur[u];i!=-1;i=e[i].next) 83 { 84 int to=e[i].to; 85 if(e[i].c>0&&lev[to]==lev[u]+1) 86 { 87 c=dfs(to,min(f-tag,e[i].c)); 88 e[i].c-=c; 89 e[i^1].c+=c; 90 tag+=c; 91 if(tag==f) return tag; 92 } 93 } 94 return tag; 95 } 96 int slove() 97 { 98 int ans=0; 99 while(bfs()) 100 { 101 FOR(i,0,n) cur[i]=head[i]; 102 ans+=dfs(S,inf); 103 } 104 return ans; 105 } 106 }flow; 107 int main() 108 { 109 cin.tie(0); 110 cout.tie(0); 111 while(~scanf("%d%d",&m,&n)) 112 { 113 flow.init(1,n); 114 while(m--) 115 { 116 si(a),si(b),si(c); 117 flow.Add(a,b,c); 118 } 119 cout<<flow.slove()<<endl; 120 } 121 return 0; 122 }
https://blog.csdn.net/huzhengnan/article/details/7766446
最大流的一些板子
https://blog.csdn.net/wjf_wzzc/article/details/24820525
sap:

1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #include<string> 7 #include<queue> 8 #include<algorithm> 9 using namespace std; 10 11 const int N=100010; 12 const int M=400010; 13 const int inf=0xfffffff; 14 15 int n,m,cnt; 16 17 struct Edge{ 18 int v , cap , next; 19 } edge[M]; 20 21 int head[N],pre[N],d[N],numd[N];//分別為鏈表的頭指針,每個點的前驅,每個點的d值,以及標號為d[i] 的點的個數 22 int cur_edge[N];//從每個點出發滿足d[i] = d[j] + 1的邊的地址 , 插入邊時的計數,源點與匯點 23 24 void addedge(int u,int v,int c){ 25 26 edge[cnt].v = v; 27 edge[cnt].cap = c; 28 edge[cnt].next = head[u]; 29 head[u] = cnt++; 30 31 edge[cnt].v = u; 32 edge[cnt].cap = 0; 33 edge[cnt].next = head[v]; 34 head[v] = cnt++; 35 } 36 37 void bfs(int s){ //先用廣度優先算出每個點的d值 38 memset(numd,0,sizeof(numd)); 39 for(int i=1; i<=n; i++) 40 numd[ d[i] = n ]++; 41 d[s] = 0; 42 numd[n]--; 43 numd[0]++; 44 queue<int> Q; 45 Q.push(s); 46 47 while(!Q.empty()){ 48 int v=Q.front(); 49 Q.pop(); 50 51 int i=head[v]; 52 while(i != -1){ 53 int u=edge[i].v; 54 55 if(d[u]<n){ 56 i=edge[i].next; 57 continue ; 58 } 59 60 d[u]=d[v]+1; 61 numd[n]--; 62 numd[d[u]]++; 63 Q.push(u); 64 i=edge[i].next; 65 } 66 } 67 } 68 69 int SAP(int s,int t){ 70 for(int i = 1; i <= n; i++) 71 cur_edge[i] = head[i]; //當前滿足d[i] = d[j] + 1的邊的為第一條邊 72 int max_flow=0; 73 bfs(t); 74 int u = s ;//從源點搜一條到匯點的增廣路 75 while(d[s]<n){//就算所有的點連成一條線源點的d值也是最多是n-1 76 if(u == t){//如果找到一條增廣路徑 77 int cur_flow = inf,neck;//找到那條瓶頸邊 78 for(int from = s; from != t; from = edge[cur_edge[from]].v){ 79 if(cur_flow > edge[cur_edge[from]].cap){ 80 neck = from; 81 cur_flow = edge[cur_edge[from]].cap; 82 } 83 } 84 85 for(int from = s; from != t; from = edge[cur_edge[from]].v){ //修改增廣路上的邊的容量 86 int tmp = cur_edge[from]; 87 edge[tmp].cap -= cur_flow; 88 edge[tmp^1].cap += cur_flow; 89 } 90 max_flow += cur_flow;//累加計算最大流 91 u = neck;//下一次搜索直接從瓶頸邊的前一個節點搜起 92 } 93 94 int i; 95 for(i = cur_edge[u]; i != -1; i = edge[i].next) //從當前點開始找一條允許弧 96 if(edge[i].cap && d[u] == d[edge[i].v]+1)//如果找到跳出循環 97 break; 98 99 if(i!=-1){//找到一條允許弧 100 cur_edge[u] = i;//從點u出發的允許弧的地址 101 pre[edge[i].v] = u;//允許弧上下一個點的前驅為u 102 u = edge[i].v;//u變成下一個點繼續搜直到搜出一條增廣路 103 } 104 else{//如果沒有搜到允許弧 105 numd[d[u]]--; //d[u]將被修改所以numd[d[u]]減一 106 if(!numd[d[u]]) break; //如果沒有點的d值為d[u]則不可能再搜到增廣路結束搜索 107 cur_edge[u] = head[u]; //當前點的允許弧為第一條邊 108 int tmp = n; 109 for(int j = head[u]; j != -1; j = edge[j].next) //搜與u相連的點中d值最小的 110 if(edge[j].cap && tmp > d[edge[j].v]) 111 tmp = d[edge[j].v]; 112 113 d[u] = tmp+1; //修改d[u] 114 numd[d[u]]++; 115 if(u != s) 116 u = pre[u];//從u的前驅搜,因為從u沒有搜到允許弧 117 } 118 } 119 return max_flow; 120 } 121 inline void pre_init(){ 122 cnt = 0; 123 memset(head, -1, sizeof head); 124 } 125 126 void mapping(){ 127 int u, v, w; 128 for(int i = 1; i <= m; ++i){ 129 scanf("%d %d %d", &u, &v, &w); 130 addedge(u, v, w); 131 } 132 } 133 134 int main(){ 135 while(~scanf("%d%d",&m,&n)){ 136 pre_init(); 137 mapping(); 138 int s,t; 139 s = 1;t = n; 140 int ans = SAP(s,t); 141 printf("%d\n",ans); 142 } 143 return 0; 144 }
dinic:

1 //dinic 2 3 #include <algorithm> 4 #include <iostream> 5 #include <string.h> 6 #include <cstdio> 7 #include <queue> 8 using namespace std; 9 const int inf = 0x3f3f3f3f; 10 const int maxn = 205; 11 const int maxm = maxn*maxn; 12 struct node{int w; int v, next;} edge[maxm]; 13 int pre[maxn], rec[maxn], head[maxn], block[maxn]; 14 int dis[maxn]; 15 int n, m, no; 16 int S, T; 17 queue<int> q; 18 inline void init(){ 19 no = 0; 20 memset(head, -1, sizeof head); 21 } 22 inline void add(int u, int v, int w){ 23 edge[no].v = v; edge[no].w = w; 24 edge[no].next = head[u]; head[u] = no++; 25 edge[no].v = u; edge[no].w = 0; 26 edge[no].next = head[v]; head[v] = no++; 27 } 28 void reset(int S, int T){ 29 memset(dis, 0x3f, sizeof dis); 30 memset(block, 0, sizeof block); 31 q.push(S); dis[S] = 0; 32 while(!q.empty()){ 33 int top = q.front(); q.pop(); 34 for(int k = head[top]; k != -1; k = edge[k].next) 35 if(dis[edge[k].v] == inf && edge[k].w) 36 dis[edge[k].v] = dis[top]+1, q.push(edge[k].v); 37 } 38 } 39 int dinic(int S, int T){ 40 int ans = 0, flow = inf; 41 int top = S; 42 reset(S, T); pre[S] = S; 43 while(dis[T] != inf){ 44 int k, tmp; 45 for(k = head[top]; k != -1; k = edge[k].next){ 46 if(edge[k].w && dis[edge[k].v]==dis[top]+1 && 47 !block[edge[k].v]) break; 48 } 49 if(k != -1){ 50 tmp = edge[k].v; 51 flow = min(flow, edge[k].w); 52 pre[tmp] = top, rec[tmp] = k; 53 top = tmp; 54 if(top == T){ 55 ans += flow; tmp = -1; 56 for(; top != S; top = pre[top]){ 57 edge[rec[top]].w -= flow; 58 edge[rec[top]^1].w += flow; 59 if(!edge[rec[top]].w) tmp = top; 60 } 61 flow = inf; 62 if(tmp != -1){ 63 top = pre[tmp]; 64 for(; top != S; top = pre[top]) 65 flow = min(flow, edge[rec[top]].w); 66 top = pre[tmp]; 67 } 68 } 69 } 70 else{ 71 block[top] = 1; 72 top = pre[top]; 73 if(block[S]) reset(S, T); 74 } 75 } 76 return ans; 77 } 78 void mapping(){ 79 int u, v, w; 80 for(int i = 1; i <= m; ++i){ 81 scanf("%d %d %d", &u, &v, &w); 82 add(u, v, w); 83 } 84 } 85 int main(){ 86 while(~scanf("%d %d", &m, &n)){ 87 S = 1, T = n; 88 init(); 89 mapping(); 90 printf("%d\n", dinic(S, T)); 91 } 92 return 0; 93 }
感謝https://www.cnblogs.com/Asumi/p/9751117.html
【最大流之Dinic算法】POJ1273 【 & 當前弧優化 & 】
https://www.cnblogs.com/DF-yimeng/p/8583698.html
//dinic

#include <algorithm> #include <iostream> #include <string.h> #include <cstdio> #include <queue> using namespace std; const int inf = 0x3f3f3f3f; const int maxn = 205; const int maxm = maxn*maxn; struct node { int w; int v, next; } edge[maxm]; int pre[maxn], rec[maxn], head[maxn], block[maxn]; int dis[maxn]; int n, m, no; int S, T; queue<int> q; inline void init() { no = 0; memset(head, -1, sizeof head); } inline void add(int u, int v, int w) { edge[no].v = v; edge[no].w = w; edge[no].next = head[u]; head[u] = no++; edge[no].v = u; edge[no].w = 0; edge[no].next = head[v]; head[v] = no++; } void reset(int S, int T) { memset(dis, 0x3f, sizeof dis); memset(block, 0, sizeof block); q.push(S); dis[S] = 0; while(!q.empty()) { int top = q.front(); q.pop(); for(int k = head[top]; k != -1; k = edge[k].next) if(dis[edge[k].v] == inf && edge[k].w) dis[edge[k].v] = dis[top]+1, q.push(edge[k].v); } } int dinic(int S, int T) { int ans = 0, flow = inf; int top = S; reset(S, T); pre[S] = S; while(dis[T] != inf) { int k, tmp; for(k = head[top]; k != -1; k = edge[k].next) { if(edge[k].w && dis[edge[k].v]==dis[top]+1 && !block[edge[k].v]) break; } if(k != -1) { tmp = edge[k].v; flow = min(flow, edge[k].w); pre[tmp] = top, rec[tmp] = k; top = tmp; if(top == T) { ans += flow; tmp = -1; for(; top != S; top = pre[top]) { edge[rec[top]].w -= flow; edge[rec[top]^1].w += flow; if(!edge[rec[top]].w) tmp = top; } flow = inf; if(tmp != -1) { top = pre[tmp]; for(; top != S; top = pre[top]) flow = min(flow, edge[rec[top]].w); top = pre[tmp]; } } } else { block[top] = 1; top = pre[top]; if(block[S]) reset(S, T); } } return ans; } void mapping() { int u, v, w; for(int i = 1; i <= m; ++i) { scanf("%d %d %d", &u, &v, &w); add(u, v, w); } } int main() { while(~scanf("%d %d", &m, &n)) { S = 1, T = n; init(); mapping(); printf("%d\n", dinic(S, T)); } return 0; }