zoukankan      html  css  js  c++  java
  • SAM I AM UVA

    /**
    题目:SAM I AM UVA - 11419
    链接:https://vjudge.net/problem/UVA-11419
    题意:给定n*n的矩阵,'X'表示障碍物,'.'表示空格;你有一把枪,每一发子弹可以消除一行或者一列的障碍物,
    问最少需要多少颗子弹可以清空障碍物?以及输出具体的哪些行,哪些列。
    
    思路:最小点集覆盖问题,等价于最大匹配。
    
    求具体的哪些行,哪些列,需要借助于匈牙利树。从X中所有未匹配的点出发扩展匈牙利树,标记
    树中的所有点,则X中所有的未标记点和Y中的所有标记点就是结果。证明。。留给读者思考~~~(来自lrj训练指南P356)
    */
    
    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<map>
    #include<vector>
    #include<queue>
    #include<set>
    #include<cstring>
    using namespace std;
    const int MAXN = 1005;
    int f[MAXN][MAXN];
    int vis[MAXN], vit[MAXN], S[MAXN], T[MAXN], flag[MAXN];
    int N;
    ///模板
    bool Find(int x)///走交替路,寻找增广路
    {
        vis[x] = 1;///标记走交替路过程中左边经过的点。
        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;
    }
    int main()
    {
        int n, m, k;
        while(scanf("%d%d%d",&n,&m,&k)==3)
        {
            if(n==0&&m==0&&k==0) break;
            N = n;
            int x, y;
            memset(f, 0, sizeof f);
            for(int i = 1; i <= k; i++){
                scanf("%d%d",&x,&y);
                f[x][y] = 1;
            }
            int ans = 0;
            memset(T, 0, sizeof T);
            memset(S, 0, sizeof S);
            memset(flag, 0, sizeof flag);
            ///模板
            for(int i = 1; i <= N; i++){
                memset(vis, 0, sizeof vis);
                memset(vit, 0, sizeof vit);
                if(Find(i)) ans++;
            }
            printf("%d",ans);
            memset(vis, 0, sizeof vis);
            memset(vit, 0, sizeof vit);
            for(int i = 1; i <= N; i++){
                if(S[i]==0){///从未匹配点出发,走交替路,不可能找到增广路,否则原先的匹配不是最大的。所以S,T数组的值不会更新。
                    Find(i);
                }
            }
            for(int i = 1; i <= N; i++){
                if(vis[i]==0){
                    printf(" r%d",i);
                }
            }
            for(int i = 1; i <= N; i++){
                if(vit[i]){
                    printf(" c%d",i);
                }
            }
            printf("
    ");
        }
        return  0;
    }
  • 相关阅读:
    read 命令详解
    rpm 命令详解
    random 模块
    time 模块
    Numpy 数据类型和基本操作
    numpy 数组对象
    netstat 命令详解
    free 命令详解
    Python中*args和**kwargs 的简单使用
    Numpy 数组简单操作
  • 原文地址:https://www.cnblogs.com/xiaochaoqun/p/7210338.html
Copyright © 2011-2022 走看看