首页 > 代码库 > poj3020 Antenna Placement 匈牙利算法求最小覆盖=最大匹配数(自身对应自身情况下要对半) 小圈圈圈点

poj3020 Antenna Placement 匈牙利算法求最小覆盖=最大匹配数(自身对应自身情况下要对半) 小圈圈圈点

/**
题目:poj3020 Antenna Placement
链接:http://poj.org/problem?id=3020
题意:
给一个由‘*‘或者‘o‘组成的n*m大小的图,你可以用一个小圈圈圈住两个相邻的‘*‘,问要圈住所有的‘*‘最少需要多少个小圈圈。(小圈圈可以相交)

思路:
先尽量圈出能圈两个且不重复圈的‘*‘。剩下的没有圈的‘*‘一定需要用一个。
所以构造二分图,求最大匹配,结果:ans = 总的‘*‘数量-最大匹配数*2 + 最大匹配数 = 总的‘*‘数量-最大匹配数;

用自身对应自身构造的二分图,求得的最大匹配数要对半才是上面要求的最大匹配数。

*/

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<map>
#include<vector>
#include<queue>
#include<set>
#include<cstring>
using namespace std;
const int MAXN = 405;///n*m=400
int f[MAXN][MAXN];
int vit[MAXN], S[MAXN], T[MAXN];
int N;
///模板
bool Find(int x)///走交替路,寻找增广路
{
    for(int i = 1; i <= N; i++){///n表示右侧点数。
        if(f[x][i]&&vit[i]==0){
            vit[i] = 1;
            if(T[i]==0||Find(T[i])){
                T[i] = x;///右边第i个点和左边第x个点匹配成功。
                S[x] = i;///左边第x个点和右边第i个点匹配成功。
                return true;
            }
        }
    }
    return false;
}
char str[42][12];
int main()
{
    int n, m, k;
    cin>>k;
    while(k--){
        scanf("%d%d",&n,&m);
        N = n*m;
        for(int i = 1; i <= n; i++){
            scanf("%s",str[i]+1);
        }
        memset(f, 0, sizeof f);
        memset(S, 0, sizeof S);
        memset(T, 0, sizeof T);
        int cnt = 0;///‘*‘的个数
        for(int i = 1; i <= n; i++){
            for(int j = 1; j <= m; j++){
                if(str[i][j]==*){
                    cnt++;
                    if(j+1<=m&&str[i][j+1]==*){///向右边,和下边找,以免重复。
                        f[(i-1)*m+j+1][(i-1)*m+j] = f[(i-1)*m+j][(i-1)*m+j+1] = 1;///两边都是相同的数据,所以最大匹配数结果是两倍。
                        ///最终要除以2。
                    }
                    if(i+1<=n&&str[i+1][j]==*){
                        f[i*m+j][(i-1)*m+j] = f[(i-1)*m+j][i*m+j] = 1;
                    }
                }
            }
        }
        int ans = 0;
        for(int i = 1; i <= N; i++){
            memset(vit, 0, sizeof vit);
            if(Find(i)) ans++;
        }
        printf("%d\n",cnt-2*(ans/2)+(ans/2));/// cnt - ans/2;
    }
    return 0;
}

 

poj3020 Antenna Placement 匈牙利算法求最小覆盖=最大匹配数(自身对应自身情况下要对半) 小圈圈圈点