zoukankan      html  css  js  c++  java
  • uva 11419 最大匹配(最小点覆盖)

    链接:https://vjudge.net/problem/27475

    题意:给定一个二维矩阵,在一些格子里放置了东西,然后你有一门炮,每次能横向或纵向开一炮,将这一行所有的东西摧毁。问你最少花多少炮弹摧毁所有的东西?并输出一组解。

    题解:

      很久之前做的题目了,今天在看到的时候还是很有新的体会的。这是一个求最小覆盖的问题,最小点覆盖,将行列的每个点看作是x,y集合,将放置的东西的地方看作是边(大白书)。然后求一次最大匹配,会得出来至少有多个点是不在同一行和同一列的,这样剩余的东西就会与原来的已匹配的点在同一行或者同一列,求完最大匹配后,可以得出开枪的次数,然后进行求方案数。从未匹配的点开始拓展,第一次没有参与匹配的点 在哪一行最多 或者在哪一列最多 那么肯定开枪位置就在这一行 或者这一列,这里的左右集合表现的很明显,因为记录 路径的缘故。

    参考代码:

    #include <stdio.h>
    #include <algorithm>
    #include <math.h>
    #include <string.h>
    #include <vector>
    #include <queue>
    #include <stack>
    #include <iostream>
    #define INF 0x3f3f3f3f
    using namespace std;
    const int maxn=1011;
    int mp[maxn][maxn];
    int machl[maxn],machr[maxn],visx[maxn],visy[maxn];
    int n,m,k;
    bool dfs(int u)
    {
        visx[u]=1;
        for(int i=1;i<=m;i++)
            if(!visy[i]&&mp[u][i])
            {
                visy[i]=true;
                if(machr[i]==-1||dfs(machr[i]))
                {
                    machl[u]=i;//列匹配
                    machr[i]=u;//行匹配
                    return true;
                }
            }
        return false;
    }
    int Maxmach()
    {
        int ans=0;
        memset(machl,-1,sizeof(machl));
        memset(machr,-1,sizeof(machr));
        for(int i=1;i<=n;i++)
        {
            memset(visy,0,sizeof(visy));
            if(dfs(i))
                ans++;
        }
        return ans;
    }
    int  main()
    {
        //freopen("C:\Users\Administrator\Desktop\a.txt","r",stdin);
        int a,b;
        while(scanf("%d%d%d",&n,&m,&k),n+m+k)
        {
            memset(mp,0,sizeof(mp));
            for(int i=0;i<k;i++)
                scanf("%d%d",&a,&b),mp[a][b]=1;
            int Ans=Maxmach();
            printf("%d",Ans);
    
    
            //求方案数
    
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof visy);
            for(int i=1;i<=n;i++)  //从x中未匹配的点出发
                if(machl[i]==-1) dfs(i);
            for(int i=1;i<=n;i++)
                if(!visx[i]) printf(" r%d",i);
            for(int i=1;i<=m;i++)
                if(visy[i]) printf(" c%d",i);
            printf("
    ");
        }
        return 0;
    }

      

  • 相关阅读:
    JAVA学习前应该了解
    JAVA帝国的诞生
    常用的快捷方式
    MarkDown学习
    运动检测
    图像分割
    感知机
    线性判别函数
    距离
    概率密度估计笔记——非参数估计
  • 原文地址:https://www.cnblogs.com/MeowMeowMeow/p/7592641.html
Copyright © 2011-2022 走看看