/** 题目:poj3041 Asteroids 链接:http://poj.org/problem?id=3041 题意:给定n*n的矩阵,'X'表示障碍物,'.'表示空格;你有一把枪,每一发子弹可以消除一行或者一列的障碍物, 问最少需要多少颗子弹可以清空障碍物? 思路:最小点集覆盖问题,等价于最大匹配。把所有的行看做二分图的左边的节点,所有的列看做二分图右边的节点。 如果f[i][j]==true;那么第i行与第j列有关系,连一条边。对这个二分图求最大匹配即可。 采用匈牙利算法。 匈牙利算法学习推荐网址:http://blog.csdn.net/dark_scope/article/details/8880547/ */ #include<iostream> #include<cstdio> #include<algorithm> #include<map> #include<vector> #include<queue> #include<set> #include<cstring> using namespace std; int f[505][505]; int vis[505], g[505]; int n; ///模板 bool Find(int x) { for(int i = 1; i <= n; i++){///n表示右侧点数。 if(f[x][i]&&vis[i]==0){ vis[i] = 1; if(g[i]==0||Find(g[i])){ g[i] = x; return true; } } } return false; } int main() { int m; while(scanf("%d%d",&n,&m)==2) { int x, y; memset(f, 0, sizeof f); for(int i = 1; i <= m; i++){ scanf("%d%d",&x,&y); f[x][y] = 1; } int ans = 0; memset(g, 0, sizeof g); ///模板 for(int i = 1; i <= n; i++){ memset(vis, 0, sizeof vis); if(Find(i)) ans++; } printf("%d ",ans); } return 0; }