hdu 5093 二分匹配

来源:互联网 发布:30岁后的美工 编辑:程序博客网 时间:2024/04/30 19:23
/*题意:给你一些冰岛。公共海域和浮冰,冰岛可以隔开两个公共海域,浮冰无影响求选尽可能多的选一些公共海域点每行每列仅能选一个。限制条件:冰山可以隔开这个限制条件。即*#*可以选两个预处理:*******#*#*****   可以按行转化  *******#ooooo*#*****按行转化的基础上按列转化***o**o**ooooooooo*oo**o**o*因为每行每列顶多可以增加50所以总共最多2500*2500的矩阵然后直接二分匹配即可*/#include<stdio.h>#include<string.h>#define N  2800int ma[N][N];char s[60][60];int ans[N][N];int n,m,addx,addy;void slovex() {//按行转化  int i,k;  addx=0;for(i=1;i<=n;i++) {addx++; //printf("%d\n",addx); k=1;while(1) {    for(;s[i][k]!='#'&&k<=m;k++) {      if(s[i][k]=='*')       ans[addx][k]=1;    }    if(k==m)//最后一个也要算进去,刚开始这里错了一直没看出来重要*****        ans[addx][k]=2;    if(k==m+1||k==m)        break;    ans[addx][k]=2;    k++;    addx++;}}return ;}void slovey() {//在按行转化的基础上按列转化 int i,k; addy=0; for(i=1;i<=m;i++) {    addy++;    k=1; //   printf("%d\n",addy);    while(1) {        for(;ans[k][i]!=2&&k<=addx;k++) {            if(ans[k][i]==1)                ma[k][addy]=1;        }        if(k==addx+1||k==addx)            break;            k++;        addy++;    } } return;}int vis[N],link[N];int findd(int u) {int i;for(i=1;i<=addy;i++)if(ma[u][i]&&vis[i]==0) {vis[i]=1;if(link[i]==-1||findd(link[i])) {link[i]=u;return 1;}}return 0;}int main() {    int t,i,sum,j;    scanf("%d",&t);    while(t--) {        scanf("%d%d",&n,&m);        memset(ma,0,sizeof(ma));        memset(ans,0,sizeof(ans));        for(i=1;i<=n;i++)            scanf("%s",s[i]+1);        slovex();       /*     for(i=1;i<=addx;i++) {                for(j=1;j<=m;j++)            printf("%d ",ans[i][j]);            printf("\n");        }*/        slovey();      /*   for(i=1;i<=addx;i++) {                for(j=1;j<=addy;j++)            printf("%d ",ma[i][j]);            printf("\n");        }*/        memset(link,-1,sizeof(link));        sum=0;        for(i=1;i<=addx;i++) {//直接套模板二分匹配即可            memset(vis,0,sizeof(vis));            sum+=findd(i);        }    printf("%d\n",sum);    }return 0;}

0 0
原创粉丝点击