HDU 1045 fire net 二分图匹配

http://acm.hdu.edu.cn/showproblem.php?pid=1045

题意:类似于八皇后,但是如果中间有墙隔开的话,皇后是可以放在一列或一行的。

题解:竖着看,将一列中连在一起的格子看成一个点,这些点就是X集。然后横着看按行缩点,这些点就是Y集。如果一行格子与一列格子相交了,那么这两个点相连。求最大匹配就可以了。

代码:

#include <iostream>
#include<cstdio>
#include<cstring>
using namespace std;
char mp[20][20];
int g[40][40];
int mpr[20][20],mpc[20][20];
int r_num,c_num;
int vis[40],used[40];
bool dfs(int r){
	int i;
	for(i=1;i<=c_num;i++){
		if(!vis[i]&&g[r][i]){
			vis[i]=1;
			if(used[i]==-1||dfs(used[i])){
				used[i]=r;
				return true;
			}
		}
	}
	return false;
}
int xiongyali(){
	memset(used,-1,sizeof(used));
	int ans=0,i;
	for(i=1;i<=r_num;i++){
		memset(vis,0,sizeof(vis));
		if(dfs(i))ans++;
	}
	return ans;
}
int main()
{
	int i,j,n;
	while(~scanf("%d",&n)){
		if(n==0)break;
		memset(mpr,0,sizeof(mpr));
		memset(mpc,0,sizeof(mpc));
		memset(g,0,sizeof(g));
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				cin>>mp[i][j];
				if(mp[i][j]=='X'){
					mpr[i][j]=-1;
					mpc[i][j]=-1;
				}
			}
		}
		int tot=0;
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				while(mpc[i][j]==-1&&j<=n){
					j++;
				}
				tot++;
				while(mpc[i][j]!=-1&&j<=n){
					mpc[i][j]=tot;
					c_num=tot;
					j++;
				}
			}
		}
		tot=0;
		for(j=1;j<=n;j++){
			for(i=1;i<=n;i++){
				while(mpr[i][j]==-1&&i<=n)i++;
				tot++;
				while(mpr[i][j]!=-1&&i<=n){
					mpr[i][j]=tot;
					r_num=tot;
					i++;
				}
			}
		}
		for(i=1;i<=n;i++){
			for(j=1;j<=n;j++){
				if(mpr[i][j]!=-1&&mpc[i][j]!=-1){
					g[mpr[i][j]][mpc[i][j]]=1;
				}
			}
		}
		printf("%d\n",xiongyali());
	}
    //cout << "Hello world!" << endl;
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值