传送门
大意:N*N的方格里有K个障碍物(小行星)。我们要清除这些障碍物。对于每一次操作,我们可以清除一行或一列上的障碍物。求最少的操作次数。
建模:把每一行每一列看做一个状态。如果i行j列有一个障碍,就把第i行和第j列连一条边。这样我们的问题就转化成了最小点覆盖(想想为什么,因为每一列或每一行是一个点,我们就要求最少的点使得每一个边(障碍物)被覆盖)
根据K?nig定理,我们知道 最小点覆盖 = 最大匹配,所以就开做了!
#include<cstdio>
#include<cstring>
#define MAXN 1100
#define MAXM 30000
struct 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;
}
版权声明:请随意转载O(∩_∩)O
原文地址:http://blog.csdn.net/gengmingrui/article/details/47106215