POJ3041 Asteroids【二分图最小点覆盖】

题目链接:

?id=3041

题目大意:

有一个N*N的矩阵,有些格子上有障碍物(坐标为(x,y) ),在消除这些障碍物的时候,可以一次性消除

该障碍物同一行所有的障碍物,,或是一次性消除该障碍物同一列所有的障碍物。只能选择清理该行或是

清理该列。问:最小进行多少次消除,就可以清理所有的障碍物。

思路:

可以将每一行当做一个点,这样总共有N个点,作为二分图的一边。将每一列当做一个点,这样又有N

个点,作为二分图的另一边。将有障碍物的行点和列点连接起来,每次只能选择行或是列,需要清除所

有的障碍物。所以不能存在一条边两边的点都没有被选中的情况。这样问题就转变为选择最少的一些点

(行点或是列点),使得从这些点与所有的边相连,也就是二分图最小点覆盖问题。

AC代码:

#include<iostream>#include<algorithm>#include<cstdio>#include<cstring>using namespace std;const int MAXN = 550;bool Map[MAXN][MAXN],Mask[MAXN];int NX,NY;int cx[MAXN],cy[MAXN];int FindPath(int u){for(int i = 1; i <= NY; ++i){if(Map[u][i] && !Mask[i]){Mask[i] = 1;if(cy[i] == -1 || FindPath(cy[i])){cy[i] = u;cx[u] = i;return 1;}}}return 0;}int MaxMatch(){for(int i = 1; i <= NX; ++i)cx[i] = -1;for(int i = 1; i <= NY; ++i)cy[i] = -1;int res = 0;for(int i = 1; i <= NX; ++i){if(cx[i] == -1){for(int j = 1; j <= NY; ++j)Mask[j] = 0;res += FindPath(i);}}return res;}int main(){int N,M,u,v;while(~scanf("%d%d",&N,&M)){NX = NY = N;memset(Map,0,sizeof(Map));for(int i = 1; i <= M; ++i){scanf("%d%d",&u,&v);Map[u][v] = 1;}printf("%d\n",MaxMatch());}return 0;}

在乎的是沿途的风景以及看风景的心情,让心灵去旅行!

POJ3041 Asteroids【二分图最小点覆盖】

相关文章:

你感兴趣的文章:

标签云: