zoukankan      html  css  js  c++  java
  • POJ 1149 最大流<建图> PIGS

    题意:

    给出猪圈个数 m 和买家人数 n

    然后给出m个猪圈的猪的头数..

    接下来 n 行..

    给出mm a1 a2 .. a(mm) k 例如 2 1 5 3 表示第i+1个用户 有mm(2) 个猪圈的钥匙 就是有第 a1(1) 个和第 a2(5) 个猪圈的钥匙..还想要买得k头猪..

    问最多能够卖出多少头..

    思路:

    其实就是最大流~

    唯一有趣的是建图的过程..

    /************************************/

    建一个超级源点0..超级汇点n+1

    以客户作为节点..

     

    超级源点根据第一个拥有猪圈的客户和超级源点连线..容量就是第一个客户累计可以得到多少头猪..

    因为第一个打开猪圈的客户可以取得所有的猪..所以超级源点和客户之间的连线容量就表示第一个打开猪圈的人虽能够得到的数量..

    然后接下来的每一个人与前一个打开猪圈的人之间连线..容量为INF..因为可以从别的猪圈调猪过来..

    然后求得的最大流就是可以卖得的猪的数量..

    /**********************************/

    Tips:

    很喜欢这道题建图的技巧~感觉很有才~~~很聪明~~虽然..可能很基础~

    大体就是上面说的了~其中用到了last数组来记录该猪圈上一个拥有钥匙的人~

    Code:

    View Code
     1 #include <stdio.h>
     2 #include <cstring>
     3 #include <queue>
     4 #include <algorithm>
     5 using namespace std;
     6 #define clr(x) memset(x, 0, sizeof(x))
     7 const int INF = 0x1f1f1f1f;
     8 const int MAXN = 110;
     9 
    10 int cap[MAXN][MAXN], flow[MAXN][MAXN];
    11 int p[MAXN], a[MAXN];
    12 int f, n;
    13 
    14 void EK(int s, int t)
    15 {
    16     queue<int> q;
    17     memset(flow, 0, sizeof(flow));
    18     memset(a, 0, sizeof(a));
    19     memset(p, 0, sizeof(p));
    20     f = 0;
    21     while(1)
    22     {
    23         memset(a, 0, sizeof(a));
    24         a[s] = INF;
    25         q.push(s);
    26         while(!q.empty())
    27         {
    28             int u = q.front();
    29             q.pop();
    30             for(int v = 0; v <= n+1; ++v)
    31             if(!a[v] && cap[u][v] > flow[u][v])
    32             {
    33                 p[v] = u;
    34                 q.push(v);
    35                 a[v] = a[u] < cap[u][v] - flow[u][v]? a[u]:cap[u][v] - flow[u][v];
    36             }
    37         }
    38         if(a[t] == 0) break;
    39         for(int u = t; u != s; u = p[u])
    40         {
    41             flow[p[u]][u] += a[t];
    42             flow[u][p[u]] -= a[t];
    43         }
    44         f += a[t];
    45     }
    46 }
    47 
    48 
    49 int main()
    50 {
    51     int i, j, k;
    52     int nn, mm;
    53     int tmp, m;
    54     int s, t;
    55     int h[1010];
    56     int last[1010];
    57 
    58     while(scanf("%d %d", &mm, &nn) != EOF)
    59     {
    60         clr(cap);
    61         clr(last);
    62         s = 0, t = nn+1;
    63         n = nn;
    64 
    65         for(i = 1; i <= mm; ++i)
    66             scanf("%d", &h[i]);
    67 
    68         for(i = 1; i <= nn; ++i){
    69             scanf("%d", &m);
    70             for(j = 0; j < m; ++j){
    71                 scanf("%d", &tmp);
    72                 if(last[tmp] == 0)
    73                     cap[s][i] += h[tmp];
    74                 else
    75                     cap[last[tmp]][i] = INF;
    76                 last[tmp] = i;
    77             }
    78             scanf("%d", &cap[i][t]);
    79         }
    80 
    81         EK(s, t);
    82         printf("%d\n", f);
    83     }
    84     return 0;
    85 }
  • 相关阅读:
    超有爱的并查集
    写给想当程序员的朋友
    POJ 1961 字符串 KMP (i-next[i])
    POJ 2406 KMP算法next数组理解
    POJ 2387 Bellman双重边
    POJ 1917 字符串替换
    POJ 1062 坑爹的聘礼(枚举等级差选择性找边)
    Linux下libxml2的使用
    浙大pat 1003
    判定一棵二叉树是否是二叉搜索树
  • 原文地址:https://www.cnblogs.com/Griselda/p/2660976.html
Copyright © 2011-2022 走看看