码迷,mamicode.com
首页 > 其他好文 > 详细

【YZOJ 1060】分配工作

时间:2015-03-10 21:17:57      阅读:165      评论:0      收藏:0      [点我收藏+]

标签:

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)

【YZOJ 1060】分配工作

标签:

原文地址:http://www.cnblogs.com/lightning34/p/4328295.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!