HDU 1150 Machine Schedule (二分图最小点覆盖)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1150

有两个机器a和b,分别有n个模式和m个模式。下面有k个任务,每个任务需要a的一个模式或者b的一个模式完成。

两个机器初始都是0模式,一个机器转换一个模式需要重启一次。问你最少需要重启几次能完成所有的任务。

不太明显的二分匹配,将每个任务的两个模式连线,大概就能看出来这是个最小点覆盖问题。

 1 /*
 2 将下面任务的a状态和b状态连边,线的个数就是任务个数。
 3 要使重启次数最少,那么就要使选择的点最少而且覆盖所有的边
 4 所以问题转化为二分图求最小点覆盖数
 5 */
 6 //二分图中 最小点覆盖 = 最大匹配数
 7 #include <iostream>
 8 #include <cstring>
 9 #include <cstdio>
10 #include <vector>
11 using namespace std;
12 vector <int> G[105];
13 int match[105];
14 bool vis[105];
15 
16 bool dfs(int u) {
17     for(int i = 0 ; i < G[u].size() ; ++i) {
18         int v = G[u][i];
19         if(!vis[v]) {
20             vis[v] = true;
21             if(match[v] == -1 || dfs(match[v])) {
22                 match[v] = u;
23                 return true;
24             }
25         }
26     }
27     return false;
28 }
29 
30 int hungry(int n) {
31     int res = 0;
32     for(int i = 1 ; i <= n - 1 ; ++i) {
33         memset(vis , false , sizeof(vis));
34         if(dfs(i))
35             res++;
36     }
37     return res;
38 }
39 
40 int main()
41 {
42     int n , m , k , id , u , v;
43     while(~scanf("%d %d %d" , &n , &m , &k) && n) {
44         for(int i = 1 ; i <= 100 ; ++i) {
45             G[i].clear();
46             match[i] = -1;
47             vis[i] = false;
48         }
49         for(int i = 0 ; i < k ; ++i) {
50             scanf("%d %d %d" , &id , &u , &v);
51             G[u].push_back(v);
52         }
53         printf("%d\n" , hungry(n));
54     }
55     return 0;
56 }

 

posted @ 2016-07-14 16:28  Recoder  阅读(251)  评论(0编辑  收藏  举报