zoukankan      html  css  js  c++  java
  • Hdu 4292 Food.cpp 最大流+拆点

    题意:

    给出 n 个人喜欢吃的食物和喜欢喝的饮料以及每种食物和饮料的数量

    如果这个人可以吃到喜欢的食物则会感到高兴

    问最多可以使多少人高兴

    给出 n f d 表示现在有 n 个人 f 种食物还有d种饮料

    接下去一行有 f 个数表示第 i 种食物的数量

    接下去一行有 d 个数表示第 i 种饮料的数量

    然后n行有f个数 Y表示喜欢第 i 种食物 N表示不喜欢

    然后n行有d个数 Y N 意思一样

     

    求出最多高兴的人数

    思路:

    建图求最大流..

    就是把食物当成超级源点 饮料当成超级汇点

    然后超级源点与每个人之间有连线 容量为食物的数量

    超级汇点和每个人之间也有连线 容量为饮料的数量

    然后根据每个人喜欢哪种食物或者是哪种饮料来连线

    因为一个人只能选一种饮料和一种食物 所以拆点..然后容量为 1

    Tips:

    当用顶点容量限制的时候就使用拆点..

    即确保这个点只会被用一次..

    在这道题..拆点就把食物和饮料的限制连在一起了..

     

    Code:

    View Code
      1 #include <cstdio>
      2 #include <cstring>
      3 #include <climits>
      4 #define clr(x) memset(x, 0xff, sizeof(x))
      5 #define min(a,b)(a)<(b)?(a):(b)
      6 
      7 const int INF = 0x1f1f1f1f;
      8 const int maxn = 100010;
      9 const int maxm = 200010;
     10 struct Edge
     11 {
     12     int from;
     13     int to;
     14     int next;
     15     int w;
     16 }edge[maxm];
     17 int tot;
     18 int head[maxn];
     19 
     20 void add(int s, int u, int f1, int f2)
     21 {
     22     edge[tot].from = s;
     23     edge[tot].to = u;
     24     edge[tot].w = f1;
     25     edge[tot].next = head[s];
     26     head[s] = tot++;
     27     edge[tot].from = u;
     28     edge[tot].to = s;
     29     edge[tot].w = f2;
     30     edge[tot].next = head[u];
     31     head[u] = tot++;
     32 }
     33 
     34 int q[maxn];
     35 int cnt[maxn];
     36 int d[maxn];
     37 int low[maxn];
     38 int cur[maxn];
     39 
     40 int maxflow(int s, int t, int n)
     41 {
     42     int *front = q, *rear = q;
     43     for(int i = 1; i <= n; ++i) {
     44         d[i] = n;
     45         cnt[i] = 0;
     46     }
     47     cnt[n] = n-1;
     48     cnt[0]++;
     49     d[t] = 0;
     50     *rear++ = t;
     51     while(front < rear) {
     52         int v = *front++;
     53         for(int i = head[v]; i != -1; i = edge[i].next) {
     54             if(d[edge[i].to] == n && edge[i^1].w > 0) {
     55                 d[edge[i].to] = d[v] + 1;
     56                 cnt[n]--;
     57                 cnt[d[edge[i].to]]++;
     58                 *rear++ = edge[i].to;
     59             }
     60         }
     61     }
     62 
     63     int flow = 0, u = s, top = 0;
     64     low[0] = INF;
     65     for(int i = 1; i <= n; ++i) {
     66         cur[i] = head[i];
     67     }
     68     while(d[s] < n) {
     69         int &i = cur[u];
     70         for(; i != -1; i = edge[i].next) {
     71             if(edge[i].w > 0 && d[u] == d[edge[i].to]+1) {
     72                 low[top+1] = min(low[top], edge[i].w);
     73                 q[++top] = i;
     74                 u = edge[i].to;
     75                 break;
     76             }
     77         }
     78         if(i != -1) {
     79             if(u == t) {
     80                 int minf = low[top];
     81                 for(int p = 1, i; p <= top; ++p) {
     82                     i = q[p];
     83                     edge[i].w -= minf;
     84                     edge[i^1].w += minf;
     85                 }
     86                 flow += minf;
     87                 u = s;
     88                 low[0] = INF;
     89                 top = 0;
     90             }
     91         }
     92         else {
     93             int old_du = d[u];
     94             cnt[old_du]--;
     95             d[u] = n-1;
     96             for(int i = head[u]; i != -1; i = edge[i].next)
     97                 if(edge[i].w > 0 && d[u] > d[edge[i].to]) {
     98                     d[u] = d[edge[i].to];
     99                 }
    100                 cnt[++d[u]]++;
    101                 if(d[u]<n)
    102                     cur[u] = head[u];
    103                 if(u != s) {
    104                     u = edge[q[top]].from;
    105                     --top;
    106                 }
    107                 if(cnt[old_du] == 0) break;
    108         }
    109     }
    110     return flow;
    111 }
    112 
    113 int main()
    114 {
    115     int i, j, k;
    116     int n, f, d;
    117     int fo, dr;
    118     char cc;
    119     while(scanf("%d %d %d", &n, &f, &d) != EOF)
    120     {
    121         clr(head);
    122         tot = 0;
    123 
    124         for(i = 2; i <= f+1; ++i) {
    125             scanf("%d", &fo);
    126             add(1, i, fo, 0);
    127         }
    128         int tt = f+d+2*n+2;
    129         for(i = f+2*n+2; i < tt; ++i) {
    130             scanf("%d", &dr);
    131             add(i, tt, dr, 0);
    132         }
    133 
    134         for(i = f+2; i < n+f+2; ++i) {
    135             getchar();
    136             for(j = 2; j <= f+1; ++j) {
    137                 scanf("%c", &cc);
    138                 if(cc == 'Y') add(j, i, 1, 0);
    139             }
    140         }
    141 
    142         for(i = f+2; i < f+n+2; ++i)
    143             add(i, i+n, 1, 0);
    144 
    145         for(i = f+n+2; i < f+2*n+2; ++i) {
    146             getchar();
    147             for(j = f+2*n+2; j < f+2*n+d+2; ++j) {
    148                 scanf("%c", &cc);
    149                 if(cc == 'Y') add(i, j, 1, 0);
    150             }
    151         }
    152 
    153         int ans = maxflow(1, f+2*n+d+2, f+2*n+d+2);
    154         printf("%d\n", ans);
    155     }
    156     return 0;
    157 }

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4292

  • 相关阅读:
    uva 562
    uva 624
    hdu 3826
    CF 89 div2 A
    看视屏学编程之接口、抽象类
    看视频学编程之SQL数据库基础
    看视频学编程之WinForm
    看视频学编程之骑士飞行棋—自己做(单机版)
    看视频学编程之继承
    看视频学编程之C#中的类
  • 原文地址:https://www.cnblogs.com/Griselda/p/2691416.html
Copyright © 2011-2022 走看看