• 【最大流】bzoj1711: [Usaco2007 Open]Dining吃饭


    正在网络流入门(原来这种题用网络流做)

    Description

    农夫JOHN为牛们做了很好的食品,但是牛吃饭很挑食. 每一头牛只喜欢吃一些食品和饮料而别的一概不吃.虽然他不一定能把所有牛喂饱,他还是想让尽可能多的牛吃到他们喜欢的食品和饮料. 农夫JOHN做了F (1 <= F <= 100) 种食品并准备了D (1 <= D <= 100) 种饮料. 他的N ( 1 <= N <= 100)头牛都以决定了是否愿意吃某种食物和喝某种饮料. 农夫JOHN想给每一头牛一种食品和一种饮料,使得尽可能多的牛得到喜欢的食物和饮料. 每一件食物和饮料只能由一头牛来用. 例如如果食物2被一头牛吃掉了,没有别的牛能吃食物2.

    Input

    * 第一行: 三个数: N, F, 和 D

    * 第2..N+1行: 每一行由两个数开始F_i 和D_i, 分别是第i 头牛可以吃的食品数和可以喝的饮料数.下F_i个整数是第i头牛可以吃的食品号,再下面的D_i个整数是第i头牛可以喝的饮料号码.

    Output

    * 第一行: 一个整数,最多可以喂饱的牛数.


    题目分析

    首先将源点连向所有食物;所有饮料连向汇点。接下来是中间奶牛的部分,容易发现如果简单地食物-奶牛-饮料一连,将会导致一头奶牛可能吃了很多饮料食物。这里有一种巧妙的处理方法:将一头奶牛拆成两个点,中间连一条容量为1的边,意味着一头牛只能占有一个食物/饮料。

    话说这题在bzoj为什么会莫名其妙TLE啊……

     1 #include<bits/stdc++.h>
     2 const int maxn = 1035;
     3 const int maxm = 10035;
     4 const int INF = 2e9;
     5 
     6 struct Edge
     7 {
     8     int u,v,f,c;
     9     Edge(int a=0, int b=0, int c=0, int d=0):u(a),v(b),f(c),c(d) {}
    10 }edges[maxm];
    11 int n,f,d,S,T,lv[maxn];
    12 int edgeTot,head[maxn],nxt[maxm];
    13 
    14 int read()
    15 {
    16     char ch = getchar();
    17     int num = 0, fl = 1;
    18     for (; !isdigit(ch); ch = getchar())
    19         if (ch=='-') fl = -1;
    20     for (; isdigit(ch); ch = getchar())
    21         num = (num<<1)+(num<<3)+ch-48;
    22     return num*fl;
    23 }
    24 void addedge(int u, int v, int c)
    25 {
    26     edges[edgeTot] = Edge(u, v, 0, c), nxt[edgeTot] = head[u], head[u] = edgeTot++; 
    27     edges[edgeTot] = Edge(v, u, 0, 0), nxt[edgeTot] = head[v], head[v] = edgeTot++; 
    28 }
    29 bool buildLevel()
    30 {
    31     memset(lv, 0, sizeof lv);
    32     std::queue<int> q;
    33     q.push(S), lv[S] = 1;
    34     for (int tmp; q.size(); )
    35     {
    36         tmp = q.front(), q.pop();
    37         for (int i=head[tmp]; i!=-1; i=nxt[i])
    38         {
    39             int v = edges[i].v;
    40             if (!lv[v]&&edges[i].f < edges[i].c){
    41                 lv[v] = lv[tmp]+1, q.push(v);
    42                 if (v==T) return true;
    43             }
    44         }
    45     }
    46     return false;
    47 }
    48 int fndPath(int x, int lim)
    49 {
    50     if (x==T) return lim;
    51     for (int i=head[x]; i!=-1; i=nxt[i])
    52     {
    53         int v = edges[i].v, val;
    54         if (lv[x]+1==lv[v]&&edges[i].f < edges[i].c){
    55             if ((val = fndPath(v, std::min(lim, edges[i].c-edges[i].f)))){
    56                 edges[i].f += val, edges[i^1].f -= val;
    57                 return val;
    58             }else lv[v] = -1;
    59         }
    60     }
    61     return 0;
    62 }
    63 int dinic()
    64 {
    65     int ret = 0, val;
    66     while (buildLevel())
    67         while ((val = fndPath(S, INF))) ret += val;
    68     return ret;
    69 }
    70 int main()
    71 {
    72     memset(head, -1, sizeof head);
    73     n = read(), f = read(), d = read();
    74     S = 0, T = n*2+f+d+1;
    75     for (int i=1; i<=n; i++)
    76     {
    77         int k1 = read(), k2 = read();
    78         for (; k1; --k1)
    79             addedge(read(), f+i, 1);
    80         for (; k2; --k2)
    81             addedge(f+i+n, read()+n*2+f, 1);
    82         addedge(f+i, f+i+n, 1);
    83     }
    84     for (int i=1; i<=f; i++) addedge(S, i, 1);
    85     for (int i=1; i<=d; i++) addedge(f+2*n+i, T, 1);
    86     printf("%d
    ",dinic());
    87     return 0;
    88 }

    END

  • 相关阅读:
    多线程编程1-定义理解与三种实现方式
    Java类集框架详细汇总-底层分析
    Trie、并查集、堆、Hash表学习过程以及遇到的问题
    spring前导知识-Tomcat、Maven等配置
    双指针、位运算、离散化、区间合并的手动模拟
    单点登录原理与简单实现
    Spring引入外部配置文件
    Java异常机制
    Java多线程-线程的概念和创建
    java webservice服务器端获取request对象的三种方式
  • 原文地址:https://www.cnblogs.com/antiquality/p/10351733.html
Copyright © 2020-2023  润新知