poj1273 Drainage Ditches (最大流裸题)

问题描述

每当约翰的田里下雨,贝西最喜欢的三叶草地里就会形成一个池塘。这意味着三叶草被水覆盖了一段时间,需要很长时间才能重新生长。因此,农夫约翰建了一套排水沟,这样贝西的苜蓿地就不会被水覆盖了。相反,水被排到附近的小溪。作为一名一流的工程师,农夫约翰还在每条水沟的开头安装了调节器,这样他就能控制水流进水沟的速度。
农夫约翰不仅知道每分钟每条沟渠能输送多少加仑的水,还知道沟渠的精确布局,这些沟渠从池塘里流出,相互流入,形成一个潜在的复杂网络。
根据所有这些信息,确定水从池塘中进入小溪的最大速度。对于任何给定的沟渠,水只朝一个方向流动,但可能有一种方式可以让水在一个圆圈中流动。

输入

输入包括几种情况。对于每种情况,第一行包含两个空格分隔的整数,N (0 <= N <= 200)和M (2 <= M <= 200)。N是农民约翰挖的沟的数目。M是这些沟渠的交叉点个数。交叉口1是池塘。交点M是流。下面N行中的每一行都包含三个整数,Si、Ei和Ci。Si和Ei (1 <= Si, Ei <= M)表示该沟渠流经的交叉口。水将通过这条沟从Si流到Ei。Ci (0 <= Ci <= 10,000,000)是水流通过沟渠的最大速度。

输出

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

Sample Input

5 4
1 2 40
1 4 20
2 4 20
2 3 30
3 4 10

Sample Output

50

分析:

裸题,不多bb。
代码自带少许注释

code(EK算法):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<algorithm>
typedef long long ll;
const int inf=0x3f3f3f3f;
const int inn=0x80808080;
using namespace std;
const int maxm=205;
int n,m;
int g[maxm][maxm];
int pre[maxm];
int mark[maxm];
int bfs(int s,int t){//bfs一遍标记反向路径
    memset(mark,0,sizeof mark);
    memset(pre,0,sizeof pre);
    pre[s]=s;
    mark[s]=1;
    queue<int>q;
    q.push(s);
    while(!q.empty()){
        int x=q.front();
        q.pop();
        for(int i=1;i<=n;i++){
            if(!mark[i]&&g[x][i]){//如果没标记过(即没走过)且容量不为0(容量为0表示没有路)
                pre[i]=x;
                mark[i]=1;
                if(i==t)return 1;
                q.push(i);
            }
        }
    }
    return 0;
}
int ek(int s,int t){
    int ans=0;//最大流
    while(bfs(s,t)){
        int d=inf;
        for(int i=t;i!=s;i=pre[i]){//找最小detla
            if(g[pre[i]][i]<d){
                d=g[pre[i]][i];
            }
        }
        for(int i=t;i!=s;i=pre[i]){
            g[pre[i]][i]-=d;//正边减少
            g[i][pre[i]]+=d;//反边增加
        }
        ans+=d;
    }
    return ans;
}
int main(){
    while(cin>>m>>n){//个人习惯把n作为节点数量,m作为路径数量,和这题题目是反的
        memset(g,0,sizeof g);//容量为0表示没有路
        for(int i=1;i<=m;i++){
            int a,b,c;
            cin>>a>>b>>c;
            g[a][b]+=c;//重边合并成一条边
        }
        cout<<ek(1,n)<<endl;
    }
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_44178736/article/details/94987884