将行、列分别看成一个集合,在某个行列上的小行星看作是连接该行列的边,故本题可以看作是求最小点覆盖数。 #include <iostream> #include <cstring> #include <cstdio> using namespace std; const int N = 501; int n, k; //网格大小,星星个数 bool map[N][N]; //i行到j列有个小星星 bool v[N]; //从第i行开始有木有访问过第j列 int link[N]; //第j列连接的是第几行 bool dfs(int x) { for (int y = 1; y <= n; ++y) { if (map[x][y] && !v[y]) { //有边且节点y未被搜索 v[y] = true; if (link[y] == 0 || dfs(link[y])) { //如果y不属于另一个匹配,或者被y匹配到的点可以找到增广路 link[y] = x; //更新匹配M'(用M替代M') return true; } } } return false; //继续查找行下一个邻接节点 } int hungary() { int num = 0; for (int i = 1; i <= n; ++i) { memset(v, 0, sizeof(v)); //清空上次搜索时的标记 if (dfs(i)) //从行节点中寻找增广路 ++num; } return num; } int main() { //freopen("temp.txt", "r", stdin); cin >> n >> k; int x, y; for (int i = 1; i <= k; ++i) { cin >> x >> y; map[x][y] = true; } cout << hungary() << endl; return 0; }