1. 程式人生 > >3041 Asteroids(二分圖最大匹配)

3041 Asteroids(二分圖最大匹配)

題意

在一個N×N的網格上,分佈著K個行星。

Bessie擁有一種能力,每次可以消滅一行或一列的行星。

求Bessie最少需要多少次才可以消滅所有的行星。

輸入

輸入N,K
接下來K行,每行輸入2個整數x,y,表示一個行星的座標。

輸出

輸出最少的次數

思路

把每行、每列都當作一個節點,網格中的點看作這些節點的邊,即若有一個點的座標是(2,3),則認為第2行和第3列有一條邊。

問題就轉換成求最小點覆蓋問題。最少需要多少個節點就可以覆蓋所有的邊。

根據最小割定理可以知道,最小點覆蓋問題等價於最大匹配問題。

程式碼

#include <iostream>
#include <vector> #include <string> #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <set> using namespace std; const int N = 1e3 + 10; vector<int> g[N]; int c[N]; bool vis[N]; bool dfs(int u) { for (int i = 0; i < g[u].size(); i++) { int
v = g[u][i]; if (vis[v]) continue; vis[v] = true; if (c[v] == -1 || dfs(c[v])) { c[v] = u; return true; } } return false; } int main() { int n, k, t; scanf("%d%d", &n, &k); for (int i = 0; i < k; i++) { int x, y; scanf("%d%d", &x, &y); g[x].push_back(y + n); g[y + n].push_back(x); } memset
(c, -1, sizeof(c)); int res = 0; for (int i = 1; i <= n; i++) { memset(vis, false, sizeof(vis)); if (dfs(i)) res = res + 1; } printf("%d\n", res); return 0; }