zoukankan      html  css  js  c++  java
  • [USACO4.2] 草地排水

    题目背景

    在农夫约翰的农场上,每逢下雨,贝茜最喜欢的三叶草地就积聚了一潭水。这意味着草地被水淹没了,并且小草要继续生长还要花相当长一段时间。因此,农夫约翰修建了一套排水系统来使贝茜的草地免除被大水淹没的烦恼(不用担心,雨水会流向附近的一条小溪)。作为一名一流的技师,农夫约翰已经在每条排水沟的一端安上了控制器,这样他可以控制流入排水沟的水流量。

    题目描述

    农夫约翰知道每一条排水沟每分钟可以流过的水量,和排水系统的准确布局(起点为水潭而终点为小溪的一张网)。需要注意的是,有些时候从一处到另一处不只有一条排水沟。

    根据这些信息,计算从水潭排水到小溪的最大流量。对于给出的每条排水沟,雨水只能沿着一个方向流动,注意可能会出现雨水环形流动的情形。

    输入输出格式

    输入格式:

    第1行: 两个用空格分开的整数N (0 <= N <= 200) 和 M (2 <= M <= 200)。N是农夫John已经挖好的排水沟的数量,M是排水沟交叉点的数量。交点1是水潭,交点M是小溪。

    第二行到第N+1行: 每行有三个整数,Si, Ei, 和 Ci。Si 和 Ei (1 <= Si, Ei <= M) 指明排水沟两端的交点,雨水从Si 流向Ei。Ci (0 <= Ci <= 10,000,000)是这条排水沟的最大容量。

    输出格式:

    输出一个整数,即排水的最大流量。

    输入输出样例

    输入样例#1:
    5 4
    1 2 40
    1 4 20
    2 4 20
    2 3 30
    3 4 10
    输出样例#1:
    50

    说明

    题目翻译来自NOCOW。

    USACO Training Section 4.2

    网络流最大流入门题

     1 #include<iostream>
     2 #include<cstdio>
     3 #include<cstdlib>
     4 #include<cstring>
     5 #include<algorithm>
     6 #include<queue>
     7 using namespace std;
     8 
     9 const int maxn = 210;
    10 const int maxm = 1010;
    11 
    12 int n,m,inf=1<<30;
    13 int nxt[maxm],to[maxm],c[maxm],h[maxn],e_num;
    14 int lev[maxn],cur[maxn];
    15 
    16 void add(int x, int y, int z)  {nxt[e_num]=h[x],to[e_num]=y,c[e_num]=z,h[x]=e_num++;}
    17 
    18 bool bfs() {
    19     queue<int> q;
    20     for(int i=1; i<=n; i++) lev[i]=0;
    21     q.push(1),lev[1]=1;
    22     while(!q.empty())  {
    23         int u=q.front(); q.pop();
    24         for(int i=h[u]; i!=-1; i=nxt[i]) {
    25             int v=to[i];
    26             if(lev[v]==0 && c[i]>0) {
    27                 lev[v]=lev[u]+1,q.push(v);
    28                 if(v==n) return true;
    29             } 
    30         }
    31     }
    32     return false;
    33 }
    34 
    35 int dfs(int u, int f) {
    36     if(u==n) return f;
    37     int tag=0,cc;
    38     for(int &i=cur[u]; i!=-1; i=nxt[i]) {
    39         int v=to[i];
    40         if(to[i]>0 && lev[v]==lev[u]+1) {
    41             cc=dfs(v,min(f-tag,c[i]));
    42             c[i]-=cc,c[i^1]+=cc,tag+=cc;
    43             if(tag==f) return tag;
    44         }
    45     }
    46     return tag;
    47 }
    48 
    49 int max_flow() {
    50     int ans=0;
    51     while(bfs()) {
    52         for(int i=1; i<=n; i++) cur[i]=h[i];
    53         ans+=dfs(1,inf);
    54     }
    55     return ans;
    56 }
    57 
    58 int main() {
    59     scanf("%d%d", &m, &n);
    60     memset(h,-1,sizeof(h));
    61     for(int i=1; i<=m; i++) {
    62         int x,y,z;
    63         scanf("%d%d%d", &x, &y, &z);
    64         add(x,y,z),add(y,x,0);
    65     }
    66     printf("%d", max_flow());
    67     return 0;
    68 }
  • 相关阅读:
    5.4 省选模拟赛 修改 线段树优化dp 线段树上二分
    一本通 高手训练 1782 分层图 状压dp
    luogu P3830 [SHOI2012]随机树 期望 dp
    5.2 省选模拟赛 或许 线型基
    luogu P4562 [JXOI2018]游戏 组合数学
    一本通 高手训练 1781 死亡之树 状态压缩dp
    luogu P4726 【模板】多项式指数函数 多项式 exp 牛顿迭代 泰勒展开
    4.28 省选模拟赛 负环 倍增 矩阵乘法 dp
    HDU 1756 Cupid's Arrow 计算几何 判断一个点是否在多边形内
    一本通 高手训练 1763 简单树 可持久化线段树 树链刨分 标记永久化
  • 原文地址:https://www.cnblogs.com/HLXZZ/p/7220138.html
Copyright © 2011-2022 走看看