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

题目大意

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

题解

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

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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值