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

来源:互联网 发布:软件定制报价单 编辑:程序博客网 时间:2024/04/29 05:30
题意:
      给你一个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 0
原创粉丝点击