zoukankan      html  css  js  c++  java
  • Hdu 4292 Food (最大流)

    题目链接:

      Hdu 4292 Food

    题目描述:

      有n位顾客,f种食物,d种饮料。顾客都有自己喜欢的饮料和食物,每个顾客至少得到一种食物和一种饮料才会在餐厅就餐,否则立马走人。现在问最多能满足几位顾客?

    解题思路:

      0作为源点,[1, f] 为食物,0到 [1,f] 建边,边流量为每种食物的数目。[f+1, f+n] 代表顾客,[1, f] 与[f+1, f+n]建边,为了尽量满足更多的顾客,把每个顾客与其喜欢的食物之间的边流量赋为1。为了防止增广路时一个顾客选择多种食物和多种饮料的情况,应该对顾客进行拆点。[f+n+1, f+n+n]也代表顾客,[f+1, f+n]  与 [f+n+1, f+n+n] 之间连边,边流量为1。[f+n+n+1, f+n+n+d]代表饮料,f+n+n+d+1代表汇点,饮料与汇点连边,边的容量为每种饮料的数目。

      这个题目时间卡的有一丢丢紧,扎扎用以前的dinic模板时候果断tle。天真的以为是用了邻接矩阵的原因,然后换成邻接表,还是t的哭瞎!!!!,最后多调试了几次后发现,我以前的dinic模板真的有问题。扎扎今天决定要更新一下dinic模板。

      1 #include <queue>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 using namespace std;
      7 
      8 const int maxn = 810;
      9 const int N = 900000;
     10 const int INF = 0x3f3f3f3f;
     11 struct Node
     12 {
     13     int to, next, flow;
     14 } edge[N];
     15 int head[maxn], Layer[maxn], s, e, tot;
     16 int vis[maxn];
     17 
     18 void Add (int from, int to, int flow)
     19 {
     20     edge[tot].to = to;
     21     edge[tot].flow = flow;
     22     edge[tot].next = head[from];
     23     head[from] = tot++;
     24 }
     25 
     26 bool CountLayer ()
     27 {
     28     queue <int> Q;
     29     memset (Layer, 0, sizeof(Layer));
     30     Q.push(s);
     31     Layer[s] = 1;
     32     
     33     while (!Q.empty())
     34     {
     35         int u = Q.front();
     36         Q.pop();
     37         for (int i=head[u]; i!=-1; i=edge[i].next)
     38         {
     39             int v = edge[i].to;
     40             if (!Layer[v] && edge[i].flow)
     41             {
     42                 Layer[v] = Layer[u] + 1;
     43                 Q.push(v);
     44                 if (v == e)
     45                     return true;
     46             }
     47         }
     48     }
     49 
     50     return false;
     51 }
     52 
     53 int dfs (int start, int end, int maxflow)
     54 {
     55     if (start == end)
     56         return maxflow;
     57         
     58     int uflow = 0;
     59     for (int i=head[start]; i!=-1; i=edge[i].next)
     60     {
     61         
     62         int v = edge[i].to;
     63         if (Layer[v]==Layer[start]+1 && edge[i].flow)
     64         {
     65             int flow = min (maxflow-uflow, edge[i].flow);
     66             flow = dfs (v, end, flow);
     67             
     68             uflow += flow;
     69             edge[i].flow -= flow;
     70             edge[i^1].flow += flow;
     71             
     72             if (maxflow == uflow)
     73                 break;
     74         }
     75     }
     76     
     77     if (uflow == 0)
     78         Layer[start] = 0;
     79         return uflow;
     80 }
     81 int dinic ( )
     82 {
     83     int maxflow = 0;
     84     
     85     while (CountLayer ())
     86         maxflow += dfs (s, e, INF);
     87         
     88     return maxflow;
     89 }
     90 int main ()
     91 {
     92     char str[maxn];
     93     int n, f, d, v;
     94     
     95     while (scanf ("%d %d %d", &n, &f, &d) != EOF)
     96     {
     97         memset (head, -1, sizeof(head));
     98         s = tot = 0;
     99         e = f + n + n + d + 1;
    100         
    101         for (int i=1; i<=f; i++)
    102         {
    103             scanf ("%d", &v);
    104             Add (s, i, v);
    105             Add (i, s, 0);
    106         }
    107 
    108         for (int i=f+n+n+1; i<e; i++)
    109         {
    110             scanf ("%d", &v);
    111             Add (i, e, v);
    112             Add (e, i, 0);
    113         }
    114 
    115         for (int i=1; i<=n; i++)
    116         {
    117             scanf ("%s", str+1);
    118             for (int j=1; j<=f; j++)
    119                 if (str[j] == 'Y')
    120                 {
    121                     Add (j, f+i, 1);
    122                     Add (f+i, j, 0);
    123                 }
    124         }
    125         
    126         for (int i=1; i<=n; i++)
    127         {
    128             scanf ("%s", str+1);
    129             for (int j=1; j<=d; j++)
    130                 if (str[j] == 'Y')
    131                 {
    132                     Add (f+n+i, f+n+n+j, 1);
    133                     Add (f+n+n+j, f+n+i, 0);
    134                 }
    135         }
    136         
    137         for (int i=f+1; i<=f+n; i++)
    138         {
    139             Add (i, i+n, 1);
    140             Add (i+n, i, 0);
    141         }
    142         
    143         printf ("%d
    ", dinic());
    144     }
    145     return 0;
    146 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    hdu 1541 Stars(经典BIT)
    CODE[VS] 1082 线段树练习3(区间修改+区间查询)
    Luogu P3368 【模板】树状数组 2(区间修改,单点查询)
    牛客小白月赛5-I-区间(差分求前缀和+一次暴力统计)
    牛客小白月赛5-J-时间(time) (简单模拟)
    牛客小白月赛5-D-阶乘(求n内每个数的阶乘相乘后尾数为0的个数)
    CF1110C Meaningless Operations(构造题)
    洛谷4859 BZOJ3622 已经没什么好害怕的了(DP,二项式反演)
    二项式反演学习笔记
    UVAlive-7040 color(组合数学,二项式反演)
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4748341.html
Copyright © 2011-2022 走看看