【二分匹配】ZOJ 1654 Place the Robots

来源:互联网 发布:学java看什么书入门 编辑:程序博客网 时间:2024/05/16 17:43

看论文时撸过。。。

这类型应该算常见了。。。

图小 数组开大点不会死掉。。

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <math.h>#include <string>#include <iostream>#include <algorithm>using namespace std;#include <queue>#include <stack>#include <vector>#include <deque>#include <set>#include <map>#define IN      freopen ("in.txt" , "r" , stdin);#define OUT  freopen ("out.txt" , "w" , stdout);typedef long long LL;const int MAXN = 100999;//点数的最大值const int MAXM = 1000010;//边数的最大值const LL INF = 1152921504;int mp1[55][55],mp2[55][55]; char s[51][51]; const int N=2622; int use[N];   //记录y中节点是否使用int linkx[N];  //记录当前与x节点相连的y的节点int linky[N];   //记录当前与y节点相连的x的节点int mat[N][N]; //记录连接x和y的边,如果i和j之间有边则为1,否则为0int gn,gm;    //二分图中x和y中点的数目int can(int t){    int j;    for(j=1;j<=gm;j++)    {       if(use[j]==0 && mat[t][j])//y中 第j个点未被使用.且有边       {           use[j]=1;//标记           if(linky[j]==0 || can(linky[j]))//如果j点没有连接则连接就t点           {                             //有连接则重新将连j的上一点linky[j] 重新查找边、因为已经标记j点              linky[j]=t;                //  linky[j] 连接下一个相连的点;              linkx[t]=j;              return 1;           }       }    }    return 0;}int MaxMatch(){    int i,num;    num=0;    memset(linkx,0,sizeof(linkx));    memset(linky,0,sizeof(linky));    for(i=1;i<=gn;i++)//x中 第i个点    {       memset(use,0,sizeof(use));       if(can(i)) num++;    }    return num;}int main(){    int t,cas=1,n,m;    //IN;    scanf("%d",&t);    while(t--)    {        memset(mp1,0,sizeof(mp1));        memset(mp2,0,sizeof(mp2));        memset(mat,0,sizeof(mat));        printf("Case :%d\n",cas++);        scanf("%d%d",&n,&m);        for(int i=0;i<n;i++)            scanf("%s",s[i]);        gn=1;        for(int i=0;i<n;i++)        {            for(int j=0;j<m;j++)                if(s[i][j]=='o')                    mp1[i][j]=gn;                else if(s[i][j]=='#')                    gn++;            gn++;        }        gm=1;        for(int i=0;i<m;i++)        {            for(int j=0;j<n;j++)                if(s[j][i]=='o')                    mp2[j][i]=gn;                else if(s[j][i]=='#')                    gn++;            gn++;        }        for(int i=0;i<n;i++)            for(int j=0;j<m;j++)            {                mat[mp1[i][j]][mp2[i][j]]=1;            }        printf("%d\n",MaxMatch());    }    return 0;}


0 0