排水沟(Drainage Ditches)——最大流水题

http://poj.org/problem?id=1273

题意:
每次下雨的时候,农场主John 的农场里就会形成一个池塘,这样就会淹没其中一小块土地,
在这块土地上种植了Bessie 最喜欢的苜蓿。这意味着苜蓿要被水淹没一段时间,而后要花很长时
间才能重新长出来。因此,John 修建了一套排水系统,这样种植了苜蓿的土地就不会被淹没。雨
水被排到了附近的一条小河中。作为一个一流的工程师,John 还在每条排水沟的起点安装了调节阀门,这样他可以控制流入排水沟的水流的速度。
John 不仅知道每条排水沟每分钟能排多少加仑的水,而且还知道整个排水系统的布局,池塘
里的水通过这个排水系统排到排水沟、并最终排到小河中,构成一个复杂的排水网络。
给定排水系统,计算池塘能通过这个排水系统排水到小河中的最大流水速度。每条排水沟的
流水方向是单方向的,但在排水系统中,流水可能构成循环。

输入描述:
输入文件中包含多个测试数据。每个测试数据的第1 行为两个整数M 和N,用空格隔开,0
≤M≤200,2≤N≤200,其中M 是排水沟的数目,N 是这些排水沟形成的汇合结点数目。结点1
为池塘,结点N 为小河。接下来有M 行,每行描述了一条排水沟,用3 个整数来描述:Si,Ei
和Ci,其中Si 和Ei(1≤Si, Ei≤N)标明了这条排水沟的起点和终点,水流从Si 流向Ei,Ci (0≤
Ci≤10,000,000)表示通过这条排水沟的最大流水速度。

输出描述:
对输入文件中的每个测试数据,输出一行,为一个整数,表示整个排水系统可以从池塘排出
水的最大速度。

建图:

这里写图片描述

#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
const int maxn=210,INF=0x3f3f3f3f;
using namespace std;
int n,m,s,t;
struct Edge{
    int from,to,cap,flow;
    Edge(int u,int v,int c,int f):from(u),to(v),cap(c),flow(f){}
};
vector<Edge> edges;
vector<int> G[maxn];
int gap[maxn],d[maxn],cur[maxn],p[maxn];
inline void addedge(int u,int v,int c){
    edges.push_back(Edge(u,v,c,0));
    edges.push_back(Edge(v,u,0,0));
    int m=edges.size();
    G[u].push_back(m-2);
    G[v].push_back(m-1);
}
void ISAP(){
    memset(cur,0,sizeof(cur));
    memset(d,0,sizeof(d));
    memset(gap,0,sizeof(gap));
    int x=s,flow=0,a=INF;
    while(d[s]<n){
        if(x==t){
            flow+=a;
            while(x!=s){
                edges[p[x]].flow+=a;
                edges[p[x]^1].flow-=a;
                x=edges[p[x]].from;
            }
            x=s;
            a=INF;
        }
        int ok=0;
        for(int i=cur[x];i<G[x].size();++i){
            Edge& e=edges[G[x][i]];
            if(e.cap>e.flow&&d[e.to]+1==d[x]){
                p[e.to]=G[x][i];
                cur[x]=i;
                x=e.to;
                ok=1;
                a=min(a,e.cap-e.flow);
                break;
            }
        }
        if(!ok){
            int m=n;
            for(int i=0;i<G[x].size();++i){
                Edge& e =edges[G[x][i]];
                if(e.cap>e.flow) m=min(m,d[e.to]);
            }
            if(--gap[d[x]]==0) break;
            gap[d[x]=m+1]++;
            cur[x]=0;
            if(x!=s) x=edges[p[x]].from;
        }
    }
    cout<<flow<<endl;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("in.cpp","r",stdin);
#endif // ONLINE_JUDGE
    int u,v,w;
    while(scanf("%d%d",&m,&n)!=EOF){
        edges.clear();
        for(int i=0;i<maxn;++i) G[i].clear();
        while(m--){
            scanf("%d%d%d",&u,&v,&w);
            addedge(u,v,w);
        }
        s=1,t=n;
        ISAP();
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值