【二分图匹配】zoj1002Fire Net

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1002
题目描述:对一个给定的n*n的地图,放入炮塔,使得它们之间不冲突。当它们在同一行或同一列时且中间没有障碍物,冲突。求最多能放入多少炮塔。

二分图匹配经典模型。
对每一行的联通块缩点放入x集合,每一列的联通块缩点放入y集合。若联通块之间有交点,连边。之后做一次最大匹配就可以求解。

当然由于n的范围小,可以直接搜索。

#include <iostream>
#include <cstdio>
#include <cstring>
#define MAXN 125
using namespace std;

int n ,cntx ,cnty ,cx[MAXN] ,cy[MAXN] ,tmp[15][15] ;
char map[15][15] ;
bool vis[MAXN<<1] ,flag[MAXN][MAXN];

void build()
{
    memset(flag,0,sizeof flag);
    memset(tmp,0,sizeof tmp);
    cntx=1;
    for(int i=0;i<n;++i)
    {
        for(int j=0;j<n;++j)
            if(map[i][j]=='X')++cntx;
            else tmp[i][j]=cntx;
        if(map[i][n-1]!='X')++cntx;
    }

    cnty=1;
    for(int j=0;j<n;++j)
    {
        for(int i=0;i<n;++i)
            if(map[i][j]=='X')++cnty;
            else flag[tmp[i][j]][cnty]=1;
        if(map[n-1][j]!='X')++cnty;
    }

}

bool dfs(int u)
{
    for(int v=1;v<=cnty;++v)
        if(!vis[v]&&flag[u][v])
        {
            vis[v]=1;
            if(!cy[v]||dfs(cy[v]))
            {
                cx[u]=v ,cy[v]=u ;
                return 1;
            }
        }
    return 0;
}

void solve()
{
    memset(cx,0,sizeof cx);
    memset(cy,0,sizeof cy);

    int ans=0;
    for(int i=1;i<=cntx;++i)
        if(!cx[i])
        {
            memset(vis,0,sizeof(vis));
            ans+=dfs(i);
        }
    printf("%d\n",ans);
}

int main()
{
    while(~scanf("%d",&n)&&n)
    {
        for(int i=0;i<n;++i)
            scanf("%s",map[i]);
        build();
        solve();
    }
    return 0;
}

你可能感兴趣的:(二分图匹配,zoj1002)