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;
}
原文地址:https://www.cnblogs.com/xiaochaoqun/p/7210338.html