【HDOJ 1045】Fire Net--二分图

【HDOJ 1045】Fire Net

数据量很小 dfs暴力可过 不过最近在学二分图 想了想二分图的做法
根据题目要求 不能让同行或者同列出现一个以上的车(无墙状态下 因此根据行 列 构建二分图 每行上联通的一段区间标为同一个号 列同理标注 然后再遍历 发现有交界时将行与列联通 最后进行一次二分最大匹配即可

代码如下:

#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;

bool mp[17][17],vis[17];
int idx[5][5],idy[5][5];
char qp[5][6];
int n,link[17],p1,p2;

void Sd()
{
    int i,j,k;
    for(p1 = 0,i = 1; i <= n; ++i)
    {
        for(j = 1; j <= n; ++j)
        {
            if(j == 1 || qp[i][j-1] == 'X') p1++;
            idx[i][j] = p1;
        }
    }

    for(p2 = 0,j = 1; j <= n; ++j)
    {
        for(i = 1; i <= n; ++i)
        {
            if(i == 1 || qp[i-1][j] == 'X') p2++;
            idy[i][j] = p2;
        }
    }

    for(i = 1; i <= n; ++i)
    {
        for(j = 1; j <= n; ++j)
        {
            if(qp[i][j] == '.') mp[idx[i][j]][idy[i][j]] = 1;
        }
    }

}

bool can(int p)
{
    int i;
    for(i = 0; i <= p2; ++i)
    {
        if(!vis[i] && mp[p][i])
        {
            vis[i] = true;
            if(link[i] == -1 || can(link[i]))
            {
                link[i] = p;
                return 1;
            }
        }
    }
    return 0;
}

int main()
{
    int i,j,cnt,sum;
    while(~scanf("%d",&n) && n)
    {
        cnt = 0;
        for(i = 1; i <= n; ++i)
            scanf("%s",qp[i]+1);
        memset(mp,0,sizeof(mp));

        Sd();

        memset(link,-1,sizeof(link));
        for(i = 0; i <= p1; ++i)
        {
            memset(vis,0,sizeof(vis));
            if(can(i)) cnt++;
        }
        printf("%d\n",cnt);
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值