您的位置:首页 > 其它

【bzoj4554】【Tjoi2016】【Heoi2016】【游戏】【二分图匹配】

2016-07-12 19:25 381 查看

题目大意

给出一个图,有一些石头不可炸,一些软石头可炸但不可放炸弹,一些空地可放炸弹。用最多炸弹使两个炸弹互相不可炸。

题解

对于横竖连通的块标号,可放炸弹的点横竖相连,表示可以放炸弹,做二分图最大匹配即可。

code

#include<set>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define fo(i,j,k) for(int i=j;i<=k;i++)
#define fd(i,j,k) for(int i=j;i>=k;i--)
using namespace std;
int const maxn=50;
int n,m,a[maxn+10][maxn+10],to[maxn*maxn+10][maxn*maxn+10],pai[maxn*maxn+10];
bool done[maxn*maxn+10];
char ch[maxn+10][maxn+10];
bool match(int now){
fo(i,1,to[now][0])
if(!done[to[now][i]]){
done[to[now][i]]=1;
if((!pai[to[now][i]])||(match(pai[to[now][i]]))){
pai[to[now][i]]=now;
return 1;
}
}
return 0;
}
int main(){
freopen("d.in","r",stdin);
freopen("d.out","w",stdout);
scanf("%d%d\n",&n,&m);
fo(i,1,n){
fo(j,1,m)scanf("%c",&ch[i][j]);
scanf("\n");
}
int cnt=0;
fo(i,1,n)
fo(j,1,m){
if((ch[i][j]!='#')&&((ch[i][j-1]=='#')||(j==1)))cnt++;
a[i][j]=cnt;
}
int cnt2=cnt;
fo(j,1,m)
fo(i,1,n){
if((ch[i][j]!='#')&&((ch[i-1][j]=='#')||(i==1)))cnt2++;
if(ch[i][j]=='*')to[a[i][j]][++to[a[i][j]][0]]=cnt2;
}
int ans=0;
fo(i,1,cnt){
if(match(i))ans++;
memset(done,0,sizeof(done));
}
printf("%d",ans);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: