POJ3041 Asteroids(最小点覆盖)

来源:互联网 发布:店淘软件 编辑:程序博客网 时间:2024/04/29 04:29

传送门
大意:N*N的方格里有K个障碍物(小行星)。我们要清除这些障碍物。对于每一次操作,我们可以清除一行或一列上的障碍物。求最少的操作次数。

建模:把每一行每一列看做一个状态。如果i行j列有一个障碍,就把第i行和第j列连一条边。这样我们的问题就转化成了最小点覆盖(想想为什么,因为每一列或每一行是一个点,我们就要求最少的点使得每一个边(障碍物)被覆盖)

根据König定理,我们知道 最小点覆盖 = 最大匹配,所以就开做了!


#include<cstdio>#include<cstring>#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;}
0 0
原创粉丝点击