zoukankan      html  css  js  c++  java
  • Poj 2112 Optimal Milking (多重匹配+传递闭包+二分)

    题目链接:

      Poj 2112 Optimal Milking

    题目描述:

      有k个挤奶机,c头牛,每台挤奶机每天最多可以给m头奶牛挤奶。挤奶机编号从1到k,奶牛编号从k+1到k+c,给出(k+c)*(k+c)的矩阵maps,maps[i][j]代表i到j的距离,问到达挤奶机需要步行最长的奶牛最短要走多少距离?(刚开始看到题目很迷啊,怎么算测试实例答案都是1,原来是非真实存在的路径长度都记为0,那么maps中的零就是INF咯)。

    解题思路:

      因为要找出步行最长距离的奶牛最少走多远,每个奶牛到达挤奶机之前可以经过多条路径,所以我们要先进行一次floyd进行传递闭包,让maps[i][j]为i到j的最短路径。然后二分枚举奶牛的路径最大距离,每次用多重匹配判断是否合法即可。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 using namespace std;
     6 
     7 const int INF = 0x3f3f3f3f;
     8 const int maxn = 250;
     9 int maps[maxn][maxn], used[35][15], link[35], vis[35];
    10 int mid, low, high, k, c, m;
    11 void floyd (int n)
    12 {
    13     for (int k=1; k<=n; k++)
    14         for (int i=1; i<=n; i++)
    15             for (int j=1; j<=n; j++)
    16             {
    17                 maps[i][j] = min (maps[i][j], maps[i][k]+maps[k][j]);
    18                 high = max (maps[i][j], high);
    19                 low = min (low, maps[i][j]);
    20             }
    21 }
    22 bool Find (int x)
    23 {
    24     for (int i=1; i<=k; i++)
    25     {
    26         if (!vis[i] && maps[x][i]<=mid)
    27         {
    28             vis[i] = 1;
    29             if (link[i]<m)
    30             {
    31                 used[i][link[i] ++] = x;
    32                 return true;
    33             }
    34             for (int j=0; j<m; j++)
    35                 if (Find(used[i][j]))
    36                 {
    37                     used[i][j] = x;
    38                     return true;
    39                 }
    40         }
    41     }
    42     return false;
    43 }
    44 bool hungry ()
    45 {
    46     memset (link, 0, sizeof(link));
    47     for (int i=k+1; i<=k+c; i++)
    48     {
    49         memset (vis, 0, sizeof(vis));
    50         if (!Find(i))
    51             return false;
    52     }
    53     return true;
    54 }
    55 int main ()
    56 {
    57     while (scanf ("%d %d %d", &k, &c, &m) != EOF)
    58     {
    59         int n = k + c;
    60         for (int i=1; i<=n; i++)
    61             for (int j=1; j<=n; j++)
    62             {
    63                 scanf ("%d", &maps[i][j]);
    64                 if (maps[i][j] == 0 && i!=j)
    65                     maps[i][j] = INF;
    66             }
    67         high = 0, low = INF;
    68         floyd (n);
    69         int ans;
    70         while (low <= high)
    71         {
    72             mid = (low+high)/2;
    73             if (hungry())
    74             {
    75                 ans = mid;
    76                 high = mid - 1;
    77             }
    78             else
    79                 low = mid + 1;
    80         }
    81         printf ("%d
    ", ans);
    82     }
    83     return 0;
    84 }
    本文为博主原创文章,未经博主允许不得转载。
  • 相关阅读:
    [Javascript]史上最短的IE浏览器判断代码
    初学者必看:精心整理的Javascript操作JSON总结
    用实例一步步教你写Jquery插件
    学习一种新编程语言要做的14个练习
    一些实战中总结的 javascript 开发经验
    JavaScript开发规范
    jQuery性能优化
    不到30行JS代码实现的Excel表格
    javascript 执行顺序详解
    Java基础知识强化之IO流笔记58:内存操作流
  • 原文地址:https://www.cnblogs.com/alihenaixiao/p/4718221.html
Copyright © 2011-2022 走看看