hdu4185Oil Skimming 二分匹配

//n*n的油田,有的有油,有的是水,
//问用最多能覆盖多少个1*2的格子
//对每一个有油的格子,如果其上下左右有油,那么在这两个点建边
//然后求最大匹配
#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
using namespace std ;
const int maxn = 610 ;
int id[maxn][maxn] ;
char map[maxn][maxn] ;
vector<int> vec[maxn*maxn] ;
int vis[maxn*maxn] ;
int match[maxn*maxn] ;
int dx[4] = {0 , 1 ,-1 ,0} ;
int dy[4] = {1 , 0 , 0 ,-1} ;
bool find(int u)
{
    for(int i = 0 ;i < vec[u].size();i++)
    {
        int v = vec[u][i] ;
        if(!vis[v])
        {
            vis[v] = 1 ;
            if(match[v] == -1 || find(match[v]))
            {
                match[v] = u ;
                return true ;
            }
        }
    }
    return false ;
}
int main()
{
    int t ;
    scanf("%d" , &t) ;
    int cas = 0 ;
    while(t--)
    {
        int n ;
        int len = 0 ;
        scanf("%d" , &n) ;
        memset(match , -1 , sizeof(match)) ;
        for(int i = 1;i <= n*n;i++)
        vec[i].clear() ;
        for(int i = 1;i <= n;i++)
        {
            scanf("%s", &map[i][1]) ;
            for(int j = 1;j <= n;j++)
            if(map[i][j] == '#')
            id[i][j] = ++len ;
        }
        for(int i = 1;i <= n;i++)
        for(int j = 1;j <= n;j++)
        if(map[i][j] == '#')
        for(int k = 0 ;k < 4;k++)
        {
            int nx = i + dx[k] ;
            int ny = j + dy[k] ;
            if(nx < 1 || nx > n || ny < 1 || ny > n)
            continue ;
            if(map[nx][ny] == '#')
            {
                vec[id[nx][ny]].push_back(id[i][j]) ;
                vec[id[i][j]].push_back(id[nx][ny]) ;
            }
        }
        int ans = 0 ;
        for(int i = 1;i <= len;i++)
        {
            memset(vis , 0 , sizeof(vis)) ;
            if(find(i))
            ans++ ;
        }
        printf("Case %d: " , ++cas) ;
        cout<<ans/2<<endl;
    }
}




















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