Drainage Ditches(POJ-1273)(网络流—最大流)

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 (0 <= N <= 200)和M (2 <= M <= 200)。N是农民约翰挖的沟的数量。M是这些沟渠的交叉点数。路口1是池塘。交点M是流。下面N行中的每一行都包含三个整数,Si、Ei和Ci。Si和Ei (1 <= Si, Ei <= M)为该沟渠的交叉点。水将从这条沟从硅流到硅。Ci (0 <= Ci <= 10,000,000)是水流过沟渠的最大流速。

输出

对于每种情况,输出一个整数,即从池塘中排空水的最大速度。

思路:看输入和输出,能看出来这是一个网络流的最大流的题。仔细读题可以看出这是一个最大流模板题。由于刚刚熟悉了一遍最大流的三个算法,所以这里就不再多说,可以看这篇文章:https://blog.csdn.net/weixin_43846139/article/details/103251718

下面给出三种算法的解题代码。

EK算法:

#include <stdio.h>
#include <string>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <iostream>
#include <vector>
#include <queue>
typedef long long ll;
const int maxx=1010;
const int inf=0x7fffffff;
using namespace std;
int c[maxx][maxx];
int f[maxx][maxx];
int pre[maxx];
int a[maxx];
int n,m;
int bfs(int s,int t)
{
    queue<int>q;
    int flow=0;
    while(!q.empty())
        q.pop();
    memset(f,0,sizeof(f));
    while(1)
    {
        memset(a,0,sizeof(a));
        a[s]=inf;
        q.push(s);
        while(!q.empty())
        {
            int u;
            u=q.front();
            q.pop();
            for(int i=1; i<=m; i++)
            {
                if(!a[i] && c[u][i]>f[u][i])
                {
                    pre[i]=u;
                    q.push(i);
                    a[i]=min(a[u],c[u][i]-f[u][i]);
                }
            }
        }
        if(!a[t]) break;
        for(int i=t; i!=s; i=pre[i])
        {
            f[pre[i]][i]+=a[t];
            f[i][pre[i]]-=a[t];
        }
        flow+=a[t];
    }
    return flow;
}
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        memset(c,0,sizeof(c));
        memset(pre,0,sizeof(pre));
        for(int i=1;i<=n;i++)
        {
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            c[u][v]+=w;
        }
        printf("%d\n",bfs(1,m));
    }
    return 0;
}

Ford-Fulkerson算法: 

#include <iostream>
#include <algorithm>
#include <math.h>
#include <string>
#include <string.h>
#include <stdio.h>
#include <vector>
const int maxx=1010;
const int inf=0x3f3f3f3f;
using namespace std;
struct node
{
    int to;
    int cap;
    int rev;
};
vector<node>v[maxx];
bool used[maxx];
int n,m;
void add(int from,int to,int cap)
{
    v[from].push_back((node){to,cap,v[to].size()});
    v[to].push_back((node){from,0,v[from].size()-1});
}
int dfs(int s,int t,int f)
{
    if(s==t) return f;
    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));
           if(d>0)
           {
               tmp.cap-=d;
               v[tmp.to][tmp.rev].cap+=d;
               return d;
           }
        }
    }
    return 0;
}
int maxflow(int s,int t)
{
    int flow=0;
    while(1)
    {
        memset(used,0,sizeof(used));
        int f=dfs(s,t,inf);
        if(f==0)
            return flow;
        flow+=f;
    }
    return flow;
}
int main()
{
    int start,end,ci;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=0;i<m;i++)
        {
            v[i].clear();
        }
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&start,&end,&ci);
            add(start,end,ci);
        }
        printf("%d\n",maxflow(1,m));
    }
    return 0;
}

Dinic算法:

#include <stdio.h>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <string>
#include <string.h>
#include <queue>
#include <vector>
const int maxx=1010;
const int inf=0x3f3f3f3f;
using namespace std;
int n,m;
int c[maxx][maxx],dep[maxx];
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 i=1; i<=m; i++)
        {
            if(c[u][i]>0 && dep[i]==-1)
            {
                dep[i]=dep[u]+1;
                q.push(i);
            }
        }
    }
    return dep[t]!=-1;
}
int dfs(int u, int mi, int t)
{
    if(u==t)
        return mi;
    int tmp;
    for(int i=1; i<=m; i++)
    {
        if(c[u][i]>0 && dep[i]==dep[u]+1  && (tmp=dfs(i,min(mi,c[u][i]),t)))
        {
            c[u][i]-=tmp;
            c[i][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;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&u,&v,&w);
            c[u][v]+=w;
        }
        printf("%d\n",dinic());
    }
    return 0;
}
发布了204 篇原创文章 · 获赞 16 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_43846139/article/details/103252378