POJ 2446 Chessboard(二分图-网格图构图)

http://poj.org/problem?id=2446

这道题,十分的妙啊。我一开始死活想不出到底怎么做,这竟然是二分图???我往这方面想也没有结果。后来在网上看到了二分图常用的建图技巧,我看到了网格图的建图方法。方法就是染色。就按照样例来说

                                                   

大概就是这样,然后跑一遍最大匹配即可。求到最大匹配后乘以2就是可以填补多少个空格。如果这个个数和空格个数不相等,那么就是无法完全填满,否则就可以完全填满。

代码如下:

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int MAXN = 520;
int uN, vN;
int G[MAXN][MAXN];
int tmp[MAXN][MAXN];
int linker[MAXN];
bool used[MAXN];
bool dfs(int u)
{
    int v;
    for(v = 1; v <= vN; v++)
        if(G[u][v] && !used[v])
        {
            used[v] = true;
            if(linker[v] == -1 || dfs(linker[v]))
            {
                linker[v] = u;
                return true;
            }    
        }  
    return false;  
}    
int hungary()
{
    int res = 0;
    int u;
    memset(linker, -1, sizeof(linker));
    for(u = 1; u <= uN; u++)
    {
        memset(used, 0, sizeof(used));
        if(dfs(u))  
			res++;
    } 
    return res;   
}     

int main()
{
	int dir[][2] = {0,1,1,0};
	int n, m, t, x, y, ans;
	int cnt1 = 1, cnt2 = 1;
	cin >> n >> m >> t;
	ans = n * m - t;
	while(t--)
	{
		scanf("%d%d", &x, &y);
		tmp[y][x] = -1;
	} 
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
		{
			if(tmp[i][j] == -1)
				continue;
			if((i + j) % 2 == 0)
				tmp[i][j] = cnt1++;
			else
				tmp[i][j] = cnt2++;
		}
		
	for(int i = 1; i <= n; i++)
		for(int j = 1; j <= m; j++)
		{
			for(int k = 0; k < 2; k++)
			{
				x = i + dir[k][0];
				y = j + dir[k][1];
				if(x > 0 && x <= n && y > 0 && y <= m && tmp[i][j] > 0 && tmp[x][y] > 0)
				{
					if((i + j) % 2 == 0)
						G[tmp[i][j]][tmp[x][y]] = 1;
					else
						G[tmp[x][y]][tmp[i][j]] = 1;
				}
			}
		}
	uN = cnt1 - 1;
	vN = cnt2 - 1;
	t = hungary();
	if(ans == t * 2)
		cout << "YES" << endl;
	else
		cout << "NO" << endl;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值