大意:N*N的方格里有K个障碍物(小行星)。我们要清除这些障碍物。对于每一次操作,我们可以清除一行或一列上的障碍物。求最少的操作次数。
建模:把每一行每一列看做一个状态。如果i行j列有一个障碍,就把第i行和第j列连一条边。这样我们的问题就转化成了最小点覆盖(想想为什么,因为每一列或每一行是一个点,我们就要求最少的点使得每一个边(障碍物)被覆盖)
根据König定理,我们知道 最小点覆盖 = 最大匹配,所以就开做了!
#include#include #define MAXN 1100#define MAXM 30000struct node{ int v; node *next;}Edge[MAXM*2], *Adj[MAXN*2], *Mcnt = Edge;void Addedge(int u, int v){ node *t = ++Mcnt; t->v = v; t->next = Adj[u]; Adj[u] = t;}int n, m, c[MAXN *2], cnt;bool vis[MAXM];bool dfs(int u){ vis[u] = 1; for(node *p = Adj[u]; p; p = p->next) { if(vis[p->v]) continue; vis[p->v] = 1; if(!c[p->v] || dfs(c[p->v])) { c[u] = p->v; c[p->v] = u; return 1; } } return 0;}int main(){ int a, b; scanf("%d%d", &n, &m); for(int i = 1; i <= m; i ++) { scanf("%d%d", &a, &b); Addedge(a, b + n); } int ans = 0; for(int i = 1; i <= n; i ++) if(!c[i]) { memset(vis, 0, sizeof vis); ans += dfs(i); } printf("%d\n", ans); return 0;}