POJ - 1273 Drainage Ditches(最大流EK算法)

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

最大流入门题:给出n条边,m个点,给出每条边的流量,求结点1到n的最大流。
EK算法可以说是复杂度最大的最大流算法了,通过广搜找增广路,然后记录找到的一条增广路的路径,即记录路径上节点的fa,以便回溯时更新图上被减小的正向流量和被增加的反向边。

代码如下,这真的很好理解,适合新手接触网络流,但真正实用的最大流算法还得是dinic

#include<stdio.h>///最大流EK算法 O(n*m^2)
#include<queue>
#include<string.h>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=208;
const int inf=0x3f3f3f3f;
int mp[maxn][maxn],fa[maxn],flow[maxn];
int n,m;
queue<int>q;
int bfs(int s,int t)///广搜找增广路
{
    while(!q.empty())q.pop();
    memset(fa,-1,sizeof fa);
    fa[s]=0,flow[s]=inf;
    q.push(s);
    while(!q.empty())
    {
        int tmp=q.front();
        q.pop();
        if(tmp==t)break;///若从起点走到了终点则找到增广路,跳出广搜
        for(int i=1;i<=n;i++)
        {
            if(i!=s&&mp[tmp][i]>0&&fa[i]==-1)
            {
                fa[i]=tmp;///记录路径
                flow[i]=min(flow[tmp],mp[tmp][i]);///每条边的流量将是这条边以上的所有容量中最小的
                q.push(i);
            }
        }
    }
    if(fa[t]==-1)return -1;///若广搜完后发现没终点没有父节点,即没有到达,就没有增广路了,GG,找完所有增广路,可以输出最大流
    return flow[t];///返回终点的流量
}
int EK(int s,int t)
{
    int add=0,sum=0;
    while(true)
    {
        add=bfs(s,t);
        if(add==-1)break;
        int tmp=t;
        while(tmp!=s)///根据路径记录对路径增加反边并减小容量
        {
            mp[fa[tmp]][tmp]-=add;
            mp[tmp][fa[tmp]]+=add;
            tmp=fa[tmp];
        }
        sum+=add;///每获得一个增广路即把这条流加上
    }
    return sum;
}
int main()
{
    while(scanf("%d%d",&m,&n)!=EOF)
    {
        int from,to,val;
        memset(flow,-1,sizeof flow);
        memset(mp,0,sizeof mp);
        for(int i=0;i<m;i++)
        {
            scanf("%d%d%d",&from,&to,&val);
            mp[from][to]+=val;
        }
        printf("%d\n",EK(1,n));
    }
}

猜你喜欢

转载自blog.csdn.net/kuronekonano/article/details/80410593