码迷,mamicode.com
首页 > 编程语言 > 详细

POJ1469 COURSES 二分图匹配 匈牙利算法

时间:2018-01-08 01:10:47      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:dong   math   html   www.   维数   href   模拟   puts   while   

原文链接http://www.cnblogs.com/zhouzhendong/p/8232649.html


题目传送门 - POJ1469


题意概括

  在一个大矩阵中,有一些障碍点。

  现在让你用1*2的小矩形覆盖非障碍点,要求不覆盖到障碍点并且不重复覆盖,问是否可以覆盖所有非障碍点。


题解

  本题几乎是裸题。

  首先注意读入的表示障碍点的二元组(x,y)中y是行,x是列。

  这个毒性深重<差评>

 

  然后考虑算法。读者可以参考笔者的前一篇博客。

  对于相邻的非障碍点我们来回都建边。然后我们给原图按照到某一个点的曼哈顿距离的奇偶性黑白染色,发现黑的只能连向白的,白的也只可以连向黑的。于是这就是一个二分图。

  然后我们跑一炮匈牙利。

  由于连出的边是来回的,所以相当于重复计算了一次,即最大匹配数翻倍了。

  于是就恰好变成了覆盖非障碍点的最大数。直接和障碍点的总数比较即可。

  注意本题用二维数组存图会TLE(我会TLE),改成数组模拟链表就过去了。<差评++>


代码

#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <algorithm>
using namespace std;
const int N=35,K=1100;
struct Gragh{
	int cnt,y[K*4],nxt[K*4],fst[K];
	void clear(){
		cnt=0;
		memset(fst,0,sizeof fst);
	}
	void add(int a,int b){
		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
	}
}g;
int m,n,k,cnt,pl[N][N],tn[N][N],match[K],vis[K];
bool check(int x,int y){
	return 1<=x&&x<=m&&1<=y&&y<=n&&!pl[x][y];
}
bool Match(int x){
	for (int i=g.fst[x];i;i=g.nxt[i]){
		int y=g.y[i];
		if (!vis[y]){
			vis[y]=1;
			if (!match[y]||Match(match[y])){
				match[y]=x;
				return 1;
			}
		}
	}
	return 0;
}
int hungary(){
	int res=0;
	memset(match,0,sizeof match);
	for (int i=1;i<=cnt;i++){
		memset(vis,0,sizeof vis);
		if (Match(i))
			res++;
	}
	return res;
}
int main(){
	while (~scanf("%d%d%d",&m,&n,&k)){
		memset(pl,0,sizeof pl);
		memset(tn,0,sizeof tn);
		for (int i=1,a,b;i<=k;i++)
			scanf("%d%d",&b,&a),pl[a][b]=1;
		cnt=0;
		for (int i=1;i<=m;i++)
			for (int j=1;j<=n;j++)
				if (!pl[i][j])
					tn[i][j]=++cnt;
		g.clear();
		for (int i=1;i<=m;i++)
			for (int j=1;j<=n;j++){
				if (pl[i][j])
					continue;
				if (check(i,j-1))
					g.add(tn[i][j],tn[i][j-1]);
				if (check(i,j+1))
					g.add(tn[i][j],tn[i][j+1]);
				if (check(i-1,j))
					g.add(tn[i][j],tn[i-1][j]);
				if (check(i+1,j))
					g.add(tn[i][j],tn[i+1][j]);
			}
		puts((hungary()==cnt)?"YES":"NO");
	}
	return 0;
}

  

POJ1469 COURSES 二分图匹配 匈牙利算法

标签:dong   math   html   www.   维数   href   模拟   puts   while   

原文地址:https://www.cnblogs.com/zhouzhendong/p/8232649.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!