POJ 2226 二分图最小覆盖

来源:互联网 发布:linux更改文件权限777 编辑:程序博客网 时间:2024/06/11 23:24

题意:
这里写图片描述
这里写图片描述

思路:
把横着的连通块放在一个集合 竖着的放在一个集合

如果有交 就连边
求最小覆盖即可 (数值上等于最大匹配)

//By SiriusRen#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define N 2555*2555int n,m,first[2555],next[N],v[N],tot,cnt,change[55][55],changea[55][55],vis[2555],matched[2555],ans;char a[55][55];void add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}bool dfs(int x){    for(int i=first[x];~i;i=next[i]){        if(!vis[v[i]]){            vis[v[i]]=1;            if(!matched[v[i]]||dfs(matched[v[i]])){                matched[v[i]]=x;                return 1;            }        }    }    return 0;}int main(){    memset(first,-1,sizeof(first));    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++){        getchar();        for(int j=1;j<=m;j++)            a[i][j]=getchar();    }    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            if(a[i][j]=='*'){                if(a[i][j-1]=='*')                    changea[i][j]=changea[i][j-1];                else changea[i][j]=++cnt;            }    for(int i=1;i<=n;i++)        for(int j=1;j<=m;j++)            if(a[i][j]=='*'){                if(a[i-1][j]=='*')                    change[i][j]=change[i-1][j];                else change[i][j]=++cnt;                add(changea[i][j],change[i][j]);            }    for(int i=1;i<=cnt;i++){        memset(vis,0,sizeof(vis));        if(dfs(i))ans++;    }    printf("%d\n",ans);}

这里写图片描述

0 0
原创粉丝点击