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+10
int 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*N
int 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;
}