• UVA-11419 SAM I AM (最小点覆盖)


    题目大意:在一个n*m的网格中,有k个目标,现在可以任选一行或列消除在其上的所有目标,求出最少选择次数及选法。

    题目分析:经典的最小点覆盖问题,并且输出一个最小点覆盖集。在求出最大匹配之后,以未覆盖的x点进行标记,沿着未覆盖->覆盖->未覆盖->覆盖...的路径标记,最后x中未标记的和y中标记的点构成最小点覆盖集。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    # define REP(i,s,n) for(int i=s;i<n;++i)
    # define CL(a,b) memset(a,b,sizeof(a))
    # define CLL(a,b,n) fill(a,a+n,b)
    
    const int N=1005;
    struct Edge
    {
        int to,nxt;
    };
    Edge e[N*N];
    int link[N],visx[N],visy[N],vis[2*N],mark[N];
    int cnt,n,m,head[N];
    
    void add(int u,int v)
    {
        e[cnt].to=v;
        e[cnt].nxt=head[u];
        head[u]=cnt++;
    }
    
    void dfs1(int x)
    {
        visx[x]=1;
        for(int i=head[x];i!=-1;i=e[i].nxt){
            int y=e[i].to;
            if(visy[y]) continue;
            visy[y]=1;
            dfs1(link[y]);
        }
    }
    
    bool dfs(int x)
    {
        for(int i=head[x];i!=-1;i=e[i].nxt){
            int y=e[i].to;
            if(vis[y]) continue;
            vis[y]=1;
            if(link[y]==-1||dfs(link[y])){
                link[y]=x;
                return true;
            }
        }
        return false;
    }
    
    int match()
    {
        int res=0;
        REP(i,1,n+1){
            CL(vis,0);
            if(dfs(i)) ++res;
        }
        return res;
    }
    
    int main()
    {
        int a,b,k;
        while(scanf("%d%d%d",&n,&m,&k)&&(n+m+k))
        {
            cnt=0;
            CL(head,-1);
            CL(link,-1);
            CL(mark,0);
            CL(visx,0);
            CL(visy,0);
            while(k--)
            {
                scanf("%d%d",&a,&b);
                add(a,b);
            }
            int ans=match();
            REP(i,1,m+1) if(link[i]!=-1) mark[link[i]]=1;
            REP(i,1,n+1) if(!mark[i]) dfs1(i);
            printf("%d",ans);
            REP(i,1,n+1) if(!visx[i]) printf(" r%d",i);
            REP(i,1,m+1) if(visy[i]) printf(" c%d",i);
            printf("
    ");
        }
        return 0;
    }
    

      

  • 相关阅读:
    [GXOI/GZOI2019] 旧词
    [HDU6756] Finding a MEX
    [洛谷P5110] 块速递推
    [CF739C] Alyona and towers
    1349. 修理牛棚
    L2-028 秀恩爱分得快 (25 分)
    L2-009 抢红包 (25 分)
    L1-043 阅览室 (20 分)
    2020年天梯赛-模拟赛 L1-6 检查密码 (15 分)
    L1-046 整除光棍 (20 分)
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/4941063.html
Copyright © 2020-2023  润新知