poj2446 2010.2.21

来源:互联网 发布:webuploader demo源码 编辑:程序博客网 时间:2024/05/22 06:19

poj2446 2010.2.21

http://blog.chinaunix.net/u3/102624/showart_2060827.html

 

题意:

 

      玩个游戏:给出一个m行n列的棋盘,里面有m*n个方格,其中有k个格子上有洞,我们称那些没洞的格子叫正常的格子(normal grid),Bob要遵循两个规则去玩:(1)任何一个正常的格子都要被一张卡覆盖,(卡片是1*2规格的)(2)一张卡要正好覆盖两个相邻的正常格子

我们的任务是帮助Bob决定是否棋盘在上述两个规则下能被覆盖。

 

思路:

因为棋盘上都是两个格子放一张卡片,所以到最后肯定是两个点两个点连着的。由此想到了二分匹配,具体是这样的:


给每个格子编号,从第一行到最后一行编号为1—12 ,然后每个点跟临近的正常点连接,这就建成了二分图,如右上图。

然后以此建邻接表,建表时,枚举每个点,如果是正常点i,那么与他相邻的正常点(v)的邻接点数增一(g[v][0]++),并使g[v][g[v][0]] = i;

然后就是二分匹配模版了,完后看匹配数是否等于正常格子数,即是否能构成完美匹配。

 

 

wa

#include <stdio.h>#include <string.h>#define MAXN 400+10int map[MAXN][MAXN];int mid[MAXN][MAXN];int link[MAXN],f[MAXN];int n,m,num1,num2,ans=0;int path(int t){int i;for(i=1;i<=n;i++){if (f[i]==0&&map[t][i]){f[i]=1;if(link[i]==-1||path(link[i])){link[i]=t;return 1;}}}return 0;}int EK(){int sum=0;int i;memset(link,-1,sizeof(link));for(i=1;i<=n;i++){memset(f,0,sizeof(f));if(path(i)) sum++;}return sum;}int main(){scanf("%d %d %d",&num1,&num2,&m);int i,j;memset(map,0,sizeof(map));memset(mid,1,sizeof(mid));for(i=1;i<=num1;i++){mid[i][0]=0;mid[i][num2+1]=0;}for(i=1;i<=num2;i++){mid[0][i]=0;mid[num1+1][i]=0;}n=num1*num2-m;int a,b;for(i=1;i<=m;i++){scanf("%d %d",&a,&b);mid[b][a]=0;}for(i=1;i<=num1;i++)for(j=1;j<=num2;j++)if (mid[i][j]){ans++;mid[i][j]=ans;}for(i=1;i<=num1;i++)for(j=1;j<=num2;j++)if (mid[i][j]){if (mid[i-1][j])map[mid[i-1][j]][mid[i][j]]=1;if (mid[i+1][j])map[mid[i+1][j]][mid[i][j]]=1;if (mid[i][j-1])map[mid[i][j-1]][mid[i][j]]=1;if (mid[i][j+1])map[mid[i][j+1]][mid[i][j]]=1;}if (EK()==n)printf("YES\n");else printf("NO\n");return 0;}

标称:

#include <stdio.h>#include <string.h>#include <conio.h>#define N 34#define M N*Nint g[M][5], used[M], mat[M];int match, m, n;int find(int k){    int i, j;    for(i=1; i<=g[k][0]; i++)    {        j = g[k][i];        if(!used[j])        {            used[j] = 1;            if(!mat[j] || find(mat[j]))            {                mat[j] = k;                return 1;            }        }    }    return 0;}void hungary(){    int i;    for(i=1; i<=m*n; i++)    {        if(g[i][0] != -1 && g[i][0] != 0)        {            match += find(i);            memset(used, 0, sizeof(used));        }    }}int main(){    int i, j;    int k;    int x, y;    freopen("in.txt", "r", stdin);    scanf("%d%d%d", &m, &n, &k);    for(i=1; i<=k; i++)    {        scanf("%d%d", &x, &y);        g[x+(y-1)*n][0] = -1;    }    for(i=1; i<=m*n; i++)    {        if(g[i][0] != -1)        {            //left            if((i-1)%n >= 1 && g[i-1][0] != -1)                g[i-1][++g[i-1][0]] = i;            //right            if(i%n != 0 && g[i+1][0] != -1)                g[i+1][++g[i+1][0]] = i;            //up            if((i-(i%n)) / n >= 1 && g[i-n][0] != -1)                g[i-n][++g[i-n][0]] = i;            //down            if((i-(i%n)+1) / n <= m && g[i+n][0] != -1)                g[i+n][++g[i+n][0]] = i;        }    }    match = 0;    hungary();        if(match == m*n-k)        printf("YES\n");    else printf("NO\n");    //printf("%d\n", match);    getch();    return 0;}


0 0