[luogu2825 HEOI2016/TJOI2016] 游戏 (二分图最大匹配)

传送门

Description

在2016年,佳缘姐姐喜欢上了一款游戏,叫做泡泡堂。简单的说,这个游戏就是在一张地图上放上若干个炸弹,看是否能炸到对手,或者躲开对手的炸弹。在玩游戏的过程中,小H想到了这样一个问题:当给定一张地图,在这张地图上最多能放上多少个炸弹能使得任意两个炸弹之间不会互相炸到。炸弹能炸到的范围是该炸弹所在的一行和一列,炸弹的威力可以穿透软石头,但是不能穿透硬石头。给定一张nm的网格地图:其中代表空地,炸弹的威力可以穿透,可以在空地上放置一枚炸弹。x代表软石头,炸弹的威力可以穿透,不能在此放置炸弹。#代表硬石头,炸弹的威力是不能穿透的,不能在此放置炸弹。例如:给出14的网格地图xx,这个地图上最多只能放置一个炸弹。给出另一个14的网格地图x#,这个地图最多能放置两个炸弹。现在小H任意给出一张n*m的网格地图,问你最多能放置多少炸弹。

Input

第一行输入两个正整数n,m,n表示地图的行数,m表示地图的列数。1≤n,m≤50。接下来输入n行m列个字符,代表网格地图。的个数不超过nm个。

Output

输出一个整数a,表示最多能放置炸弹的个数

Sample Input

4 4
#∗∗∗
∗#∗∗
∗∗#∗
xxx#

Sample Output

5

Solution

实际上就是互相影响的不能同时选择
把图按照块编号后跑最大匹配

Code

//By Menteur_Hxy
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
#define E(i,u) for(register int i=head[u];i;i=nxt[i])
#define ins(a,b,c) add(a,b,c),add(b,a,0)
#define add(a,b,c) nxt[++cnt]=head[a],to[cnt]=b,cst[cnt]=c,head[a]=cnt
using namespace std;

int read() {
	int x=0,f=1; char c=getchar();
	while(!isdigit(c)) {if(c=='-')f=-f; c=getchar();}
	while(isdigit(c)) x=(x<<1)+(x<<3)+c-48,c=getchar();
	return x*f;
}

const int N=1010,INF=0x3f3f3f3f;
int n,m,xid,yid,S,T,cnt;
int nxt[N*N],to[N*N],cst[N*N],head[N*N],cur[N*N];
int map[N][N],dx[N][N],dy[N][N],que[N*N<<2],dis[N*N];

bool bfs() {
	memset(dis,0,sizeof(dis));
	int h=0,t=1; que[++h]=S; dis[S]=1;
	while(h<=t) {
		int u=que[h++];
		E(i,u) if(!dis[to[i]]&&cst[i]>0)
			dis[to[i]]=dis[u]+1,que[++t]=to[i];
	}
	return dis[T];
}

int dfs(int u,int flow) {
	if(u==T) return flow;
	int used=0;
	for(register int &i=cur[u],v;i;i=nxt[i]) 
		if(cst[i]>0&&dis[(v=to[i])]==dis[u]+1) {
			int tmp=dfs(v,min(flow-used,cst[i]));
			cst[i]-=tmp,cst[i^1]+=tmp;
			used+=tmp; if(used==flow) return flow;
		}
	if(!used) dis[u]=-1;
	return used;	
}

int dinic() {
	int res=0;
	while(bfs()) {
		F(i,0,T) cur[i]=head[i];
		res+=dfs(S,INF);
	}
	return res;
}

int main() {
	n=read(),m=read();
	F(i,1,n) {
		scanf("\n");
		F(j,1,m) {
			char ch=getchar();
			if(ch=='x') map[i][j]=1;
			else if(ch=='#') map[i][j]=2;
		}
	}
	F(i,1,n) {
		xid++;
		F(j,1,m) 
			dx[i][j]=xid,xid+=(map[i][j]==2);
	}
	F(i,1,m) {
		yid++;
		F(j,1,n) 
			dy[j][i]=yid,yid+=(map[j][i]==2);
	}
	S=0,T=xid+yid+1,cnt=1;
	F(i,1,xid) ins(S,i,1); F(i,1,yid) ins(i+xid,T,1);
	F(i,1,n) F(j,1,m) if(!map[i][j]) 
		ins(dx[i][j],dy[i][j]+xid,1);
	printf("%d",dinic());
	return 0;
}
posted @ 2018-08-16 09:39  Menteur_hxy  阅读(143)  评论(0编辑  收藏  举报