【图论】【二分图匹配】[POJ 3041]Asteroids

来源:互联网 发布:儿童英语配音软件 编辑:程序博客网 时间:2024/05/16 01:25

首先这道题目可以发现我们可以发现如果集合S表示所有需要被覆盖的点的行和列的集合那么我们的任务就是从S中选出一个子集使得size(S)最小同时S可以覆盖所有的点。那么如果我们选择了一个行那么和当前行相关的所有的列都有可能不被再选,那么将当前行和当前行上所有点的列连接,那么我们求得就是一个最小点的覆盖集,那么ans=ans

#include <cstdio>#include <cstring>#include <algorithm>//#include <conio.h>using namespace std;const int MAXN = 1000;bool vis[MAXN+10];int con[MAXN+10];int endcnt;int n, m;struct node{    int v;    node *next;}Edges[10000*2+10], *adj[MAXN+10], *ecnt=Edges;void addedge(int u, int v){    ++ecnt;    ecnt->v = v;    ecnt->next = adj[u];    adj[u] = ecnt;}bool dfs(int u){    for(node *p=adj[u];p;p=p->next){        if(!vis[p->v]){            vis[p->v] = true;            if(con[p->v]==-1 || dfs(con[p->v])){                con[u] = p->v;                con[p->v] = u;                return true;            }        }    }    return false;}int work(){    int ret = 0;    memset(con, -1, sizeof con);    for(int i=1;i<=endcnt;i++) if(con[i] == -1){        memset(vis, 0, sizeof vis);        ret += dfs(i);    }    return ret;}void read(){    int t1, t2;    scanf("%d%d", &n, &m);    for(int i=0;i<m;i++){        scanf("%d%d", &t1, &t2);        addedge(t1, t2+n);        addedge(t2+n, t1);    }    endcnt=n;}int main(){    int T=1;    while(T--){        read();        printf("%d\n", work());        memset(adj, 0, sizeof adj);        ecnt=Edges;    }    return 0;}
0 0