Fire Net HDU - 1045 (二分图匹配)

题意:

给出一张图,图中'X'表示wall,'.'表示空地,可以放置blockhouse同一条直线上只能有一个blockhouse,除非有wall

隔开,问在给出的图中最多能放置多少个blockhous

 

分析:

把原始图分别按行和列缩点  
建图:横竖分区。先看每一列,同一列相连的空地同时看成一个点,显然这样的区域不能够同时放两个点。这些

点作为二分图的X部。同理在对所有的行用相同的方法缩点,作为Y部。  
  连边的条件是两个区域有相交部分(即'.'的地方)。最后求最大匹配就是答案。

#include <bits/stdc++.h>
using namespace std;
int n;
struct node
{
    int a = 0 , b = 0;
};
node id[6][6];
char mp[6][6];
bool link[105][105];
bool vis[105];
int use[105];
int hcnt,rcnt;

void dfsh(int x,int y){
    if(y <= n && mp[x][y] == '.'){
        id[x][y].a = hcnt;
        dfsh(x,y+1);
    }
}

void dfsr(int x,int y){
    if(x <= n && mp[x][y] == '.'){
        id[x][y].b = rcnt;
        dfsr(x+1,y);
    }
}

int find(int x)
{
    for (int s = 1; s < rcnt; s++) {
        if (link[x][s] && !vis[s]) {
            vis[s] = 1;
            if (use[s] == 0 || find(use[s])) {
                use[s] = x;
                return 1;
            }
        }
    }
    return 0;
}

int main(int argc, char const *argv[])
{
    while(cin >> n && n){
        for(int i = 1;i <= n ;i ++){
            cin >> mp[i] + 1;
        }

            memset(id,0,sizeof id);
            memset(link,0,sizeof link);
            memset(use,0,sizeof use);
            hcnt = rcnt = 1;
            for(int i = 1;i <= n;i ++){
                for(int j = 1;j <= n ;j ++){
                    if(mp[i][j] == 'X'){
                        continue;
                    }
                    if(id[i][j].a == 0){
                        dfsh(i,j);
                        hcnt ++;
                    }
                    if(id[i][j].b == 0){
                        dfsr(i,j);
                        rcnt ++;
                    }
                    link[id[i][j].a][id[i][j].b] = 1;
                }
            }
            int sum = 0;
            for(int i = 1;i < hcnt;i ++){
                memset(vis,0,sizeof vis);
                if(find(i)) sum ++;
            }
            printf("%d\n",sum );
        }

    
    return 0;
}

 

转载于:https://www.cnblogs.com/DWVictor/p/11343288.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值