zoukankan      html  css  js  c++  java
  • 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 ");
                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 ");
            else printf("NO ");
        }
        return 0;
    }







  • 相关阅读:
    栈与递归
    细说二叉树的删除操作
    二叉树
    链表队列
    数组队列
    链表栈
    c语言实现数组栈
    c语言实现双链表
    HDU 4557 非诚勿扰(Treap找后继)
    POJ 3481 Double Queue(Treap模板题)
  • 原文地址:https://www.cnblogs.com/csnd/p/12062500.html
Copyright © 2011-2022 走看看