• 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
    ",cnt-2*(ans/2)+(ans/2));/// cnt - ans/2;
        }
        return 0;
    }
  • 相关阅读:
    相对定位和绝对定位
    Html中常见的块级元素
    浮动的用法
    c#中质数判断
    函数
    asp.net Jquery+json 实现无刷新分页
    MS CRM2011 某个用户(团队)对某个实体的操作权限
    asp.net sitemap url动态参数
    MS CRM 2011 更改团队的业务部门
    MS CRM 2011 解决记录总数问题
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7214419.html
Copyright © 2020-2023  润新知