POJ2446(二分图最大匹配)

Chessboard

Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 16924   Accepted: 5284

Description

Alice and Bob often play games on chessboard. One day, Alice draws a board with size M * N. She wants Bob to use a lot of cards with size 1 * 2 to cover the board. However, she thinks it too easy to bob, so she makes some holes on the board (as shown in the figure below). 

We call a grid, which doesn’t contain a hole, a normal grid. Bob has to follow the rules below: 
1. Any normal grid should be covered with exactly one card. 
2. One card should cover exactly 2 normal adjacent grids.

Some examples are given in the figures below: 
 
A VALID solution.
 
An invalid solution, because the hole of red color is covered with a card.
 
An invalid solution, because there exists a grid, which is not covered.
Your task is to help Bob to decide whether or not the chessboard can be covered according to the rules above.

Input

There are 3 integers in the first line: m, n, k (0 < m, n <= 32, 0 <= K < m * n), the number of rows, column and holes. In the next k lines, there is a pair of integers (x, y) in each line, which represents a hole in the y-th row, the x-th column.

Output

If the board can be covered, output "YES". Otherwise, output "NO".

Sample Input

4 3 2
2 1
3 3

Sample Output

YES

思路:将两个相邻的grid建边,判断二分图最大匹配*2+k是否等于n*m
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int MAXN=40;
const int MAXV=1100;
int n,m,k;
int mz[MAXN][MAXN];
int dy[4]={0,1,0,-1};
int dx[4]={1,0,-1,0};
vector<int> arc[MAXV];
int vis[MAXN][MAXN];
int match[MAXV],used[MAXV];
bool dfs(int u)
{
    for(int i=0;i<arc[u].size();i++)
    {
        int to=arc[u][i];
        if(!used[to])
        {
            used[to]=1;
            int w=match[to];
            if(w==-1||dfs(w))
            {
                match[to]=u;
                match[u]=to;
                return true;
            }
        }
    }
    return false;
}
int max_flow()
{
    int ans=0;
    memset(match,-1,sizeof(match));
    int limit=n*m;
    for(int i=1;i<=limit;i++)
    {
        if(match[i]==-1)
        {
            memset(used,0,sizeof(used));
            if(dfs(i))
            {
                ans++;
            }
        }
    }
    return ans;
}
int main()
{
    while(scanf("%d%d%d",&n,&m,&k)!=EOF)
    {
        if((n*m-k)%2!=0)
        {
            printf("NO\n");
            continue;
        }
        for(int i=0;i<MAXV;i++)    arc[i].clear();
        memset(vis,0,sizeof(vis));
        memset(mz,0,sizeof(mz));
        for(int i=0;i<k;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            mz[y][x]=-1;
        }
        //int edge=0;
        for(int y=1;y<=n;y++)
        {
            for(int x=1;x<=m;x++)
            {
                vis[y][x]=1;
                if(mz[y][x]==-1)    continue;
                for(int i=0;i<4;i++)
                {
                    int ny=y+dy[i];
                    int nx=x+dx[i];
                    if(1<=ny&&ny<=n&&1<=nx&&nx<=m&&mz[ny][nx]!=-1&&!vis[ny][nx])
                    {
        //                edge++;
                        int u=(y-1)*m+x;
                        int v=(ny-1)*m+nx;
                        arc[u].push_back(v);
                        arc[v].push_back(u);
                    }
                }
            }
        }
        //printf("%d\n",edge);
        int res=max_flow();
        if(res*2+k==n*m)
        {
            printf("YES\n");
        }
        else
        {
            printf("NO\n");
        }
    }
    return 0;
}
时间: 2024-09-30 16:54:51

POJ2446(二分图最大匹配)的相关文章

POJ2446 Chessboard【二分图最大匹配】

题目链接: http://poj.org/problem?id=2446 题目大意: 给一个N*M的矩阵,其中有K个地方有坑.告诉你这K个坑的位置,现在要用1*2的矩形板去覆盖 矩阵,不能覆盖有坑的地方.问:是否能把除了坑之外的地方全部覆盖掉,如果能,则输出"YES", 否则输出"NO". 思路: 考虑到矩形板的规格是1*2,则相邻位置的(i,j)和(x,y)必然是(i+j)为奇数的话,(x+y)则为偶数. (i+j)为偶数的话,(x+j)则为奇数.这样,就可以把图

[POJ2446] Chessboard(二分图最大匹配-匈牙利算法)

传送门 把所有非障碍的相邻格子彼此连一条边,然后求二分图最大匹配,看 tot * 2 + k 是否等于 n * m 即可. 但是连边不能重复,比如 a 格子 和 b 格子 相邻,不能 a 连 b ,b 也连 a. 所以可以人为规定,横纵坐标相加为 奇数 的格子连横纵坐标相加为 偶数 的格子. 如果一个格子横纵坐标相加为奇数,那么它的上下左右四个格子横纵坐标相加必定为偶数. ——代码 1 #include <cstdio> 2 #include <cstring> 3 4 using

匈牙利算法dfs模板 [二分图][二分图最大匹配]

最近学了二分图最大匹配,bfs模板却死活打不出来?我可能学了假的bfs 于是用到了dfs模板 寻找二分图最大匹配的算法是匈牙利算法 匈牙利算法的主要程序是寻找增广路 寻找增光路是过程是:从一个未经配对的点出发,历经未配边.匹配边.未配边.匹配边.未配边....最终到达一个未配点的过程,只要把路径中的未配边和匹配边的“身份”对调,匹配就加一了.这就是一个寻找增广路的过程,通过不断寻找增广路,可以找到最大的匹配. 1 #include<cstdio> 2 #include<cstring&g

图论——LCA、强联通分量、桥、割顶、二分图最大匹配、网络流

A: 交通运输线 时间限制: 5 Sec  内存限制: 128 MB 题目描述 战后有很多城市被严重破坏,我们需要重建城市.然而,有些建设材料只能在某些地方产生.因此,我们必须通过城市交通,来运送这些材料的城市.由于大部分道路已经在战争期间完全遭到破坏,可能有两个城市之间没有道路.当然在运输线中,更不可能存在圈. 现在,你的任务来了.给你战后的道路情况,我们想知道,两个城市之间是否存在道路,如果存在,输出这两个城市之间的最短路径长度. 输入 第一行一个整数Case(Case<=10)表示测试数据

POJ 2226二分图最大匹配

匈牙利算法是由匈牙利数学家Edmonds于1965年提出,因而得名.匈牙利算法是基于Hall定理中充分性证明的思想,它是二部图匹配最常见的算法,该算法的核心就是寻找增广路径,它是一种用增广路径求二分图最大匹配的算法. #include<stdio.h> #include<string.h> #include<stdlib.h> int n1,n2; char map[1005][1005]; //数组开大点 int mapx[1005][1005],mapy[1005]

【Codevs1922】骑士共存问题(最小割,二分图最大匹配)

题意: 在一个n*n个方格的国际象棋棋盘上,马(骑士)可以攻击的棋盘方格如图所示.棋盘上某些方格设置了障碍,骑士不得进入. 对于给定的n*n个方格的国际象棋棋盘和障碍标志,计算棋盘上最多可以放置多少个骑士,使得它们彼此互不攻击. n<=200,m<=n^2 思路:经典的二分图最大匹配问题,采用黑白点染色的思想. 如果按照相邻点黑白不同染色,可以发现每次跳到的点必定与现在所在点不同色,二分图最大匹配即可. 这里用最小割来解决,因为不能允许任何黑白点之间的任何一条边有流量,符合最小割的思想. 1

POJ2239 Selecting Courses(二分图最大匹配)

题目链接 N节课,每节课在一个星期中的某一节,求最多能选几节课 好吧,想了半天没想出来,最后看了题解是二分图最大匹配,好弱 建图: 每节课 与 时间有一条边 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <vector> 7 using namespa

二分图最大匹配总结

hdoj1528 二分匹配模版: 代码: 1 #include<stdio.h> 2 #include<iostream> 3 #include<string.h> 4 #include<algorithm> 5 #include<math.h> 6 using namespace std; 7 #define N 220 8 9 int n, maps[N][N], vis[N], used[N]; 10 11 struct node 12 {

POJ - 1422 Air Raid 二分图最大匹配

题目大意:有n个点,m条单向线段.现在问要从几个点出发才能遍历到所有的点 解题思路:二分图最大匹配,只要一条匹配,就表示两个点联通,两个点联通只需要选取其中一个点即可,所以有多少条匹配,就可以减去多少个点 #include<cstdio> #include<cstring> using namespace std; const int N = 130; int g[N][N], vis[N], link[N]; int n, m; void init() { memset(g, 0