0
点赞
收藏
分享

微信扫一扫

POJ2446 模板盖格子 简单二分匹配

题意:
      给你一个n*m的格子,有的格子上有坑,然后让你用1*2的东西去覆盖所有没有坑的格子,不能重叠,坑上也不能放东西覆盖,问是否能成功。


思路: 
      简单题目,每个格子和四周的格子如果可以放在同一个1*2的里面那么就连接一条边,直接匹配一遍就行了,有的人可能想问为什么?可以这么想,首先如果像覆盖所有的格子那么必须是放最多的1*2覆盖物((n*m-k)/2这么多个),然后每个覆盖物会覆盖两个,也就是说必须这写覆盖物最后覆盖的都是一对一对的,把所有的点都拆成两个点,左右各一排,然后直接匹配,最后/2是不是就是能覆盖的最大的对数?so.....

#include<stdio.h>

#include<string.h>



#define N_node 1500

#define N_edge 6000



typedef struct

{

int to ,next;

}STAR;



STAR E[N_edge];

int list[N_node] ,tot;

int mkgx[N_node] ,mkdfs[N_node];

int map[32+5][32+5];



void add(int a ,int b)

{

E[++tot].to = b;

E[tot].next = list[a];

list[a] = tot;

}



int DFS_XYL(int x)

{

for(int k = list[x] ;k ;k = E[k].next)

{

int to = E[k].to;

if(mkdfs[to]) continue;

mkdfs[to] = 1;

if(mkgx[to] == -1 || DFS_XYL(mkgx[to]))

{

mkgx[to] = x;

return 1;

}

}

return 0;

}





int main ()

{

int n ,m ,q;

int a ,b ,i ,j;

while(~scanf("%d %d %d" ,&n ,&m ,&q))

{

memset(map ,0 ,sizeof(map));

for(i = 1 ;i <= q ;i ++)

{

scanf("%d %d" ,&a ,&b);

map[b][a] = 1;

}



if((n * m - q)&1)

{

printf("NO\n");

continue;

}

memset(list ,0 ,sizeof(list));

tot = 1;

for(i = 1 ;i <= n ;i ++)

for(j = 1 ;j <= m ;j ++)

{

if(map[i][j]) continue;

if(i <= n - 1 && !map[i+1][j])

add((i - 1) * m + j ,i * m + j);

if(j <= m - 1 && !map[i][j+1])

add((i - 1) * m + j ,(i - 1) * m + j + 1);

if(i >= 2 && !map[i-1][j])

add((i - 1) * m + j ,(i - 2) * m + j);

if(j >= 2 && !map[i][j-1])

add((i - 1) * m + j ,(i - 1) * m + j - 1);

}

memset(mkgx ,255 ,sizeof(mkgx));

int ans = 0;

for(i = 1 ;i <= n * m ;i ++)

{

memset(mkdfs ,0 ,sizeof(mkdfs));

ans += DFS_XYL(i);

}

if(ans == n * m - q)

printf("YES\n");

else printf("NO\n");

}

return 0;

}









举报

相关推荐

0 条评论