题目链接: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 }