题目链接:
在一个n*n的地图中,有m和障碍物,你每一次可以消除一行或者一列的障碍物,问你最少消除几次可以将障碍物全部清除。
用二分图将行(左边)和列(右边)用障碍物联系起来,比如(2,3)有个障碍物,那么左边的2和右边的3连边。边的个数就是障碍物的个数,点的个数就是次数,所以问题就变成了用少的点覆盖全部的边,也就是最小点覆盖问题。二分图中,最小点覆盖=最大匹配数。
1 //最小点覆盖 = 最大匹配 2 #include3 #include 4 #include 5 #include 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 }