标签:
题目链接:http://poj.org/problem?id=3041
在一个n*n的地图中,有m和障碍物,你每一次可以消除一行或者一列的障碍物,问你最少消除几次可以将障碍物全部清除。
用二分图将行(左边)和列(右边)用障碍物联系起来,比如(2,3)有个障碍物,那么左边的2和右边的3连边。边的个数就是障碍物的个数,点的个数就是次数,所以问题就变成了用少的点覆盖全部的边,也就是最小点覆盖问题。二分图中,最小点覆盖=最大匹配数。
1 //最小点覆盖 = 最大匹配 2 #include <iostream> 3 #include <cstdio> 4 #include <cstring> 5 #include <vector> 6 using namespace std; 7 const int N = 505; 8 struct Edge { 9 int next , to; 10 }edge[N*N]; 11 int head[N] , cnt , match[N]; 12 bool vis[N]; 13 14 void init() { 15 memset(match , -1 , sizeof(match)); 16 memset(head , -1 , sizeof(head)); 17 memset(vis , false , sizeof(vis)); 18 cnt = 0; 19 } 20 21 inline void add(int u , int v) { 22 edge[cnt].next = head[u]; 23 edge[cnt].to = v; 24 head[u] = cnt++; 25 } 26 27 bool dfs(int u) { 28 for(int i = head[u] ; ~i ; i = edge[i].next) { 29 int v = edge[i].to; 30 if(!vis[v]) { 31 vis[v] = true; 32 if(match[v] == -1 || dfs(match[v])) { 33 match[v] = u; 34 return true; 35 } 36 } 37 } 38 return false; 39 } 40 41 int hungry(int n) { 42 int res = 0; 43 for(int i = 1 ; i <= n ; ++i) { 44 memset(vis , false , sizeof(vis)); 45 if(dfs(i)) 46 res++; 47 } 48 return res; 49 } 50 51 int main() 52 { 53 int n , m , u , v; 54 while(~scanf("%d %d" , &n , &m)) { 55 init(); 56 for(int i = 0 ; i < m ; ++i) { 57 scanf("%d %d" , &u , &v); 58 add(u , v); 59 } 60 printf("%d\n" , hungry(n)); 61 } 62 return 0; 63 }
标签:
原文地址:http://www.cnblogs.com/Recoder/p/5671524.html