• 分配工作


    Description

    Zxc接到一个任务--拯救世界。好在他有N个粉丝,Zxc把世界分成N个部分,每个粉丝处理一个部分,最后他来收尾。已知每个粉丝处理每个部分所需的时间,求拯救世界的最短时间是多少。每个人同时开始,但是不能互相帮忙。也就是说每个粉丝只能处理一个部分,并且一定要处理一个。

    Input Format

    第一行一个整数N,表示Zxc粉丝的个数。接下来N行,每行N个整数。第i+1行,第j个数表示第i个粉丝第j个部分所需要的时间。

    Output Format

    一个整数,表示最少需要的时间。

    Sample Input

    3 
    1 10 100 
    10 4 3 
    4 3 1

    Sample Output

    3

    Hint

    20%的数据满足1<=N<=25;

    100%的数据满足1<=N<=800且最少需要的时间不超过10^9。

    分析:看到题目首先想到的是用匈牙利找完美匹配,但是还要求时间最少,因为每个人的工作是分开的,互不干扰,所以使时间最少就是让用时最多的人用的时间u最少,二分枚举一下答案判断是否可以找到完美匹配就行了。

    代码:

     1 #include <cstdio>
     2 #include <cstring>
     3 
     4 int n, m, t[1000][1000];
     5 int vis[1000], from[1000];
     6 int to[1000000], nxt[1000000], first[1000], en;
     7 
     8 int ins (int p1, int p2)
     9 {
    10     en++;
    11     to[en] = p2;
    12     nxt[en] = first[p1];
    13     first[p1] = en;
    14 }
    15 
    16 int draw (int lim)
    17 {
    18     memset (to, 0, sizeof (to));
    19     memset (nxt, 0, sizeof (nxt));
    20     memset (first, 0, sizeof (first));
    21     en = 0;
    22     for (int i = 1; i <= n; i++)
    23         for (int j = 1; j <= n; j++)
    24             if (t[i][j] <= lim) ins (i, j);
    25 }
    26 
    27 bool find (int a)
    28 {
    29 
    30     for (int e = first[a]; e; e = nxt[e])
    31     {
    32         if (!vis[to[e]])
    33         {
    34             vis[to[e]] = 1;
    35             if (from[to[e]] == -1 || find (from[to[e]]))
    36             {
    37                 from[to[e]] = a;
    38                 return true;
    39             }
    40         }
    41     }
    42     return false;
    43 }
    44 
    45 bool work ()
    46 {
    47     int ans = 0;
    48     memset (from, -1, sizeof (from));
    49     for (int i = 1; i <= n; i++)
    50     {
    51         memset (vis, 0, sizeof (vis));
    52         ans += find (i);
    53     }
    54     return ans == n;
    55 }
    56 
    57 int run ()
    58 {
    59     int l = 1, r = m, mid;
    60     while (l < r)
    61     {
    62         mid = (l + r) >> 1;
    63         draw (mid);
    64         if (work ()) r = mid;
    65         else l = mid + 1;
    66     }
    67     return r;
    68 }
    69 
    70 int main ()
    71 {
    72     scanf ("%d", &n); m = 0;
    73     for (int i = 1; i <= n; i++)
    74         for (int j = 1; j <= n; j++)
    75             scanf ("%d", &t[i][j]), 
    76             t[i][j] > m ? m = t[i][j] : 0;
    77     printf ("%d", run ());
    78 }

    PS:看起来好像每次都会有很多边,实际上二分下去剩得不多,用邻接矩阵一共跑了17.772s,用邻接表只跑了3.93s。(n+e只用了1.285s,ORZORZ)

  • 相关阅读:
    数论模板
    acdream1116 Gao the string!(扩展KMP)
    后缀数组模板
    Codeforces446C DZY Loves Fibonacci Numbers(线段树 or 分块?)
    acdream1116 Gao the string!(hash二分 or 后缀数组)
    SPOJ375 Query on a tree(LCT边权)
    krpano HTML5 Viewer可以实现全景展示
    Chrome 前端 插件
    canvas 星空插件
    jQuery插件开发
  • 原文地址:https://www.cnblogs.com/lightning34/p/4328295.html
Copyright © 2020-2023  润新知