poj3020-Antenna Placement(最小路径覆盖问题,最大匹配)

题目来源:http://poj.org/problem?id=3020

题意

为城镇安装无线网络(WI-FI),给出一个矩阵,矩阵里的’*’代表房子,然后’o’代表空地,也就是不是房子,然后一个无线覆盖的范围是挨着的两个房子(不可以斜着),然后问,最少需要多少个无线。。。

思路

这道题采用了拆点的思想,然后给重新分成两部分的点集加上关系(挨着的),然后就是利用匈牙利匹配得到最大匹配,利用公式:最小路径覆盖=节点数-最大匹配。

代码

//vis数组的大小是拆点之后的大小。
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int maxn=40+10;
char str[maxn][maxn];
int num[maxn][maxn],mp[maxn*maxn][maxn*maxn];
int pre[maxn*maxn],vis[maxn*maxn];
int n,m,tot;

void init()
{
    tot=0;
    scanf("%d%d",&n,&m);
    getchar();
    memset(num,0,sizeof(num));
    memset(mp,0,sizeof(mp));
    for(int i=1;i<=n;i++)
    {
        scanf("%s",str[i]+1);
        for(int j=1;j<=m;j++)
        {
            if(str[i][j]=='*')
            num[i][j]=++tot;
        }
    }
}

void deal()
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!num[i][j]) continue;
            if(i!=1&&num[i-1][j]) mp[num[i][j]][num[i-1][j]]=1;
            if(i!=n&&num[i+1][j]) mp[num[i][j]][num[i+1][j]]=1;
            if(j!=1&&num[i][j-1]) mp[num[i][j]][num[i][j-1]]=1;
            if(j!=m&&num[i][j+1]) mp[num[i][j]][num[i][j+1]]=1;
        }
    }
}

int dfs(int i)
{
    for(int j=1;j<=tot;j++)
    {
        if(mp[i][j]&&!vis[j])
        {
            vis[j]=1;
            if(pre[j]==-1||dfs(pre[j]))
            {
                pre[j]=i;
                return 1;
            }
        }
    }
    return 0;
}

void solve()
{
    deal();
    int ret=0;
    memset(pre,-1,sizeof(pre));
    for(int i=1;i<=tot;i++)
    {
        memset(vis,0,sizeof(vis));
        ret+=dfs(i);
    }
    printf("%d\n",tot-ret/2);
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        solve();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值