zoukankan      html  css  js  c++  java
  • Poj 3189 Steady Cow Assignment (多重匹配)

    题目链接:

      Poj 3189 Steady Cow Assignment

    题目描述:

      有n头奶牛,m个棚,每个奶牛对每个棚都有一个喜爱程度。当然啦,棚子也是有脾气的,并不是奶牛想住进来就住进来,超出棚子的最大容量了,棚子是拒绝的。现在要给每个奶牛安家,本宝宝是一个公正无私的人类,所以要找一个奶牛喜爱程度差值最小的方案(虽然这样大家的喜爱程度可能普遍偏低,因为绝对公平并不代表合理啊),问喜爱程度的区间最小为多大?

    解题思路:

      每个棚子并不是住一个奶牛,所以是多重匹配咯。匹配的时候二分枚举喜爱程度的区间大小,根据区间大小来枚举区间的起点和终点,然后跑多重匹配判断是否合法即可。注意咯,求得是区间大小,并不是最大喜爱程度与最小喜爱程度的差值。还有啊,还有啊,数据读入的时候maps[i][j]并不是i_th奶牛对j_th棚子的喜爱值,而是i_th奶牛对maps[i][j]棚子的喜爱程度为j。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int maxn = 1010;
     8 int maps[maxn][22], vis[22], used[22][maxn];
     9 int link[22], limit[22], n, m, s, e, mid;
    10 bool Find (int u)
    11 {
    12     for (int i=1; i<=m; i++)
    13     {//多重匹配
    14         if (!vis[i] && maps[u][i]<e && s<=maps[u][i])
    15         {
    16             vis[i] = 1;
    17             if (link[i] < limit[i])
    18             {//i棚子未满
    19                 used[i][link[i] ++] = u;
    20                 return true;
    21             }
    22             for (int j=0; j<limit[i]; j++)//i棚子已满,寻找增广路
    23                 if (Find(used[i][j]))
    24                 {
    25                     used[i][j] = u;
    26                     return true;
    27                 }
    28         }
    29     }
    30     return false;
    31 }
    32 bool hungry ()
    33 {
    34     for (s=1; s<=m+1-mid; s++)
    35     {//枚举区间起点与终点
    36         int ans = 0;
    37         e = s + mid;
    38         memset (link, 0, sizeof(link));
    39         for (int i=1; i<=n; i++)
    40         {
    41             memset (vis, 0, sizeof(vis));
    42             if (Find (i))
    43                 ans ++;
    44         }
    45         if (ans == n)
    46             return true;
    47     }
    48     return false;
    49 }
    50 int main ()
    51 {
    52     while (scanf ("%d %d", &n, &m) != EOF)
    53     {
    54         for (int i=1; i<=n; i++)
    55             for (int j=1; j<=m; j++)
    56             {
    57                 scanf ("%d", &mid);
    58                 maps[i][mid] = j;
    59             }
    60         for (int i=1; i<=m; i++)
    61             scanf ("%d", &limit[i]);
    62         int left = 1, right = m, ans = 0;
    63         while (left<=right)
    64         {//二分枚举区间
    65             mid = (right+left)/2;
    66             if (hungry())
    67                 {
    68                     ans = mid;
    69                     right = mid - 1;
    70                 }
    71             else
    72                 left = mid + 1;
    73         }
    74         printf ("%d
    ", ans);
    75     }
    76     return 0;
    77 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    linux shell获取用户输入
    yii2 笔记(1)
    yii2 数据库查询
    Yii2 环境配置生产环境和测试环境
    mysql 中find_in_set()和in()用法比较
    使用js提交form表单的两种方法
    base64编码的原理及实现
    浅析HTTP/2的多路复用
    Nginx 所使用的 epoll 模型是什么?
    git代码统计
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4709773.html
Copyright © 2011-2022 走看看