HDU 1532 Drainage Ditches (EK算法求最大流 详解)

Drainage Ditches

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 20757    Accepted Submission(s): 9950


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 41 2 401 4 202 4 202 3 303 4 10
 

Sample Output
 
 
50
 

Source

AC代码:

   EK算法求最大流:

   用队列:

#include <stdio.h>
#include <string.h>   
#include <algorithm>  
#include <cmath>   
#include <queue>    
using namespace std;  
#define INF 0x3f3f3f3f  
  
int flow[220][220];  //存放流量 
int vis[220],pre[220];  //标记是否走过该点,该点的前驱 
int n,m;  
  
int max_flow()  
{  
    int ans = 0;  
    while(1)  
    {  
        memset(vis,0,sizeof(vis));  
        memset(pre,0,sizeof(pre));  
        queue<int> Q;  
        vis[1] = 1;  
        Q.push(1);  
        while(!Q.empty())  
        {  
            int cnt = Q.front();  
            Q.pop();  
            if(cnt == n)  
                break;  
            for(int i = 1; i <= n; i++)  
                if(!vis[i] && flow[cnt][i] > 0)  
            {  
                vis[i] = 1;  
                pre[i] = cnt;  
                Q.push(i);  
            }  
        }  
        if(!vis[n])  //如果到不了汇点(即找不到增广路径了)就停止 
            break;  
        int Max = INF;  
        for(int i = n; i != 1; i = pre[i])  
            Max = min(Max,flow[pre[i]][i]);  //找这条路上的最小容量 
        for(int i = n; i != 1; i = pre[i])  
        {  
            flow[pre[i]][i] -= Max;  //正向边加上找到的最小容量 
            flow[i][pre[i]] += Max;  //反向边减去找到的最小容量 
        }  
        ans += Max;  
    }  
    return ans;  //所有的增广路径都找完了,递归过程也完成了,返回结果 
}  
int main()  
{    
    while(scanf("%d%d",&m,&n) != EOF)  
    {  
        memset(flow,0,sizeof(flow));  
        for(int i = 0; i < m; i++)  
        {  
            int u,v,w;  
            scanf("%d%d%d",&u,&v,&w);  
            flow[u][v]+=w; //注意 可能有重边 
        }  
        printf("%d\n",max_flow());  
    }  
}  

用容器:

可能写法不对,错误如下,有人能帮我解答的话最好啦

0_0_24371970_30028.cpp
0_0_24371970_30028.cpp(24) : error C2059: 语法错误:“{”
0_0_24371970_30028.cpp(24) : error C2143: 语法错误 : 缺少“;”(在“{”的前面)
0_0_24371970_30028.cpp(24) : error C2143: 语法错误 : 缺少“;”(在“}”的前面)
0_0_24371970_30028.cpp(24) : error C2143: 语法错误 : 缺少“;”(在“)”的前面)
0_0_24371970_30028.cpp(25) : error C2059: 语法错误:“{”
0_0_24371970_30028.cpp(25) : error C2143: 语法错误 : 缺少“;”(在“{”的前面)
0_0_24371970_30028.cpp(25) : error C2143: 语法错误 : 缺少“;”(在“}”的前面)
0_0_24371970_30028.cpp(25) : error C2143: 语法错误 : 缺少“;”(在“)”的前面)


#include <cstdio>  
#include <cstring>  
#include <iostream>  
#include <string>  
#include <algorithm>  
#include <map>  
#include <vector>  
using namespace std;  
const int N = 1100;  
const int INF = 0x3f3f3f3f;  
  
struct Node  
{  
    int to;//终点  
    int cap; //容量  
    int rev;  //反向边在点to的容器里存放的位置  v[2].push_back((node){4,20,1}) 意思是点2在点4的容器里的位置是1(容器里位置标号(下标)从0开始,所以点 2是第2个连接点4的点) 
};  
  
vector<Node> v[N];  
bool used[N];  
  
void add_Node(int from,int to,int cap)  //重边情况不影响 
{  
    v[from].push_back((Node){to,cap,v[to].size()});  
    //这是一条正向边,从from到to,点from是第v[to].size+1个连接to的点,在v[to]中的位置是v[to].size 
    v[to].push_back((Node){from,0,v[from].size()-1});  //这里要减1是因为v[from]先push_back进去了一个,为了使标号从0开始
	//这是一条反向边,从to到from,点to是第v[from].size个连接点from的点,在v[from]中的位置是v[from].size()-1(下标从0开始) 
}  

//这里的t值其实是不变的,一直是汇点,这个函数的目的是找出增广路径并找出这条路径上剩余容量最少的边(即汇点最多能加上多少流量),找到后返回 
int dfs(int s,int t,int f)  
{  
    if(s==t)  //如果已经从源点深搜到到汇点的路,就说明已经比较出这条路上的最小剩余容量,就是汇点能最多增加的流量 
        return f;  //返回到 d 
    used[s]=true;  //避免走回去,走重复的路,一条路径走下来应该是这条路上的点只经过一次 
    for(int i=0;i<v[s].size();i++)  
    {  
        Node &tmp = v[s][i];  //注意  
        if(used[tmp.to]==false && tmp.cap>0)  //寻找新的路线的时候,没有走过这条线,并且这条线上还有剩余容量 
        {  
            int d=dfs(tmp.to,t,min(f,tmp.cap)); //就走这条线,以tmp.to为起点s继续深搜,并且比较是否更新最小剩余流量  
            if(d>0)  //如果return了f的值到d且d>0,就说明找到了最大能增加的流量,找到了一条能到达汇点的增广路径 
            {  
                tmp.cap-=d;  //与汇点相连的那条线的容量减d 
                v[tmp.to][tmp.rev].cap+=d;  //反向边的容量增加d 
                return d;  //返回d的值到 max_flow()函数中的f 
            }  
        }   
    }  //直到for(int i=0;i<v[1].size;i++)执行完才算完成递归,次循环停止 
    return 0;  //增广路径已经找完了,返回0到max_flow中的f 
}  
  
int max_flow(int s,int t)  
{  
    int flow=0;  
    for(;;){  
        memset(used,false,sizeof(used)); //任何一条线上如果还有剩余容量的话,寻找新的增广路径的时候就还可能用上,所以标记都要清0 
        int f=dfs(s,t,INF);  //每次找最小容量的时候最小值都要赋初值为正无穷 
        if(f==0)  //找不到增广路径了  
            return flow;//返回结果 
        flow+=f;  //每成功找到一次增广路径 就 加上在各条线中找到的最小剩余容量,这样能保证这条路径上任何一条线增加的流量都不会超出自身剩余容量 
    }  
}  
int main()  
{  
    int n,m;  //n条,m个点 
    while(~scanf("%d%d",&n,&m))  
    {  
        memset(v,0,sizeof(v));  
        for(int i=0;i<n;i++)  
        {  
            int x,y,z;  
            scanf("%d%d%d",&x,&y,&z);  //起点,终点,容量 
            add_Node(x,y,z);  
        }  
        printf("%d\n",max_flow(1,m));  //1为源点,m为汇点 
    }  
} 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值