HDU 1532 Drainage Ditches (最大网络流)

本文介绍了一种解决排水沟水流最大传输率问题的方法,通过构建网络流模型并使用Ford-Fulkerson算法找到最大流,从而得出水能以最大速率从池塘流向溪流的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Drainage Ditches
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 896 Accepted Submission(s): 414


Problem 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.


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

解题:

最大网络流的模板题,从网上找了一个不错的模板,而有待理解。

#include <iostream> using namespace std; #define MAXN 205 #define INF 2110000000 #define MIN(x,y) (x<y?x:y) int map[MAXN][MAXN]; int max_flow(int num,int map[][MAXN],int source,int sink)//参数含义:结点数量 网络 源点 汇点 { int my_queue[MAXN],queue_first,queue_end;//数组做队列 实现BFS搜索路径 int pre[MAXN],min_flow[MAXN];//记录结点的父节点 当前路径中最小的一段的值,也即限制值 int flow[MAXN][MAXN];//记录当前网络中的流 int ans=0;//最终结果 memset(flow,0,sizeof(flow)); while(1)//一直循环,直到不存在增广路径 { queue_first=0;//初始化队列 queue_end=0; my_queue[queue_end++]=source; memset(pre,-1,sizeof(pre)); min_flow[source]=INF; pre[source]=-2;//源点的父节点需特殊标示 while(queue_first<queue_end)//BFS寻找增广路径 { int temp=my_queue[queue_first++];//出队列 for(int i=0;i<num;i++)//由结点temp往外扩展 { if(pre[i]==-1&&flow[temp][i]<map[temp][i])//当结点i还未被探索到,并且还有可用流量 { my_queue[queue_end++]=i;//加入队列 pre[i]=temp;//标示父节点 min_flow[i]=MIN(min_flow[temp],(map[temp][i]-flow[temp][i]));//求得min_flow } } if(pre[sink]!=-1)//sink的父节点不为初始值,说明BFS已经找到了一条路径 { int k=sink; while(pre[k]>=0) { flow[pre[k]][k]+=min_flow[sink];//将新的流量加入flow flow[k][pre[k]]=-flow[pre[k]][k]; k=pre[k]; } break; } } if(pre[sink]==-1) return ans;//不存在增广路径,返回 else ans+=min_flow[sink]; } } int main() { int m,n; while(cin>>n>>m) { int a,b,cost; memset(map,0,sizeof(map)); for(int i=0;i<n;i++) { cin>>a>>b>>cost; map[a-1][b-1]+=cost; } cout<<max_flow(m,map,0,m-1)<<endl; } return 0; }

#include <stdio.h> #include <iostream> #include <string.h> #define SIZE 201 using namespace std; int NumOfAdj, NumOfVtx; int map[SIZE][SIZE]; //图的邻接矩阵 //FIFO queue============================================ struct QUEUE { int queue[SIZE]; int head; int tail; }; struct QUEUE q; int visited[SIZE], pre[SIZE]; int InitQ() { q.head=q.tail=0; return 1; } int EnQ(int x) { q.queue[q.tail]=x; q.tail++; return 1; } int DeQ() { int x; x=q.queue[q.head]; q.head++; return x; } //===================================================== bool BFSSearchPath() { int i, u, v; bool flag; flag=false; InitQ(); for (i=2;i<=NumOfVtx;i++) { visited[i]=0; pre[i]=-1; } visited[1]=1; pre[1]=-1; EnQ(1); while (q.head!=q.tail && !flag) { u=DeQ(); for (v=1;v<=NumOfVtx;v++) { if (map[u][v]!=0 && visited[v]==0) { visited[v]=1; pre[v]=u; EnQ(v); if (v==NumOfVtx)//搜索到最短路径时返回 { flag=true; break; } } } visited[u]=2; } return flag; } int Ford_Fulkerson(int s, int t) { int Maxflow, min, u,v; Maxflow=0; while (BFSSearchPath()) { min=10000001; v=NumOfVtx; //求最短路径上的剩余流量 while (v!=1) { u = pre[v]; if (map[u][v]<min) { min=map[u][v]; } v=pre[v]; } //根据剩余流量求剩余网络 v=NumOfVtx; while (v!=1) { u = pre[v]; map[u][v]-=min; map[v][u]+=min; v=pre[v]; } Maxflow+=min; } return Maxflow; } int main() { int s, e, c, maxflow; int i; /*freopen("e://2.txt", "r", stdin);*/ while (cin>>NumOfAdj>>NumOfVtx) { memset(map, 0, sizeof(map)); for (i=0;i<NumOfAdj;i++) { cin>>s>>e>>c; map[s][e]+=c;//两点间可能有多条路径,把权值相加 } maxflow=Ford_Fulkerson(1, NumOfVtx); cout<<maxflow<<endl; } return 0; }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值