• 二分图之最小边覆盖(poj3020)


    题目:poj3020


    题意:给出一个图,让你用最少的1*2的纸片覆盖掉图中的全部*出现过的地方。

    基本裸的最小边覆盖。


    分析:

    最小边覆盖 = 点总数 - 最大匹配

    所以就是转化为求最大匹配。


    跟前面一道题目非常相似,也是同样的建图方法,奇偶性建图。


    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    const int N = 1200;
    #define Del(x,y) memset(x,y,sizeof(x))
    int map[N][N],link[N],vis[N],vlink[N];
    char path[50][50];
    int line[50][50];
    int n,m,t,tmp1,tmp2;
    bool dfs(int x)
    {
        for(int i=1; i<tmp2; i++)
        {
            if(map[x][i]==1 && vis[i]==0)
            {
                vis[i]=1;
                if(link[i]==-1 || dfs(link[i]))
                {
                    link[i]=x;
                    return true;
                }
            }
        }
        return false;
    }
    void solve()
    {
        int ans=0;
        Del(link,-1);
        for(int i=1; i<tmp1; i++)
        {
            Del(vis,0);
            if(dfs(i))
                ans++;
        }
        //printf("%d
    ",ans);
        printf("%d
    ",tmp1+tmp2-ans-2);
    }
    int main()
    {
        int T;
        scanf("%d",&T);
        //freopen("Input.txt","r",stdin);
        while(T--)
        {
            scanf("%d%d",&n,&m);
            Del(path,0);
            for(int i=1;i<=n;i++)
            {
                getchar();
                for(int j=1;j<=m;j++)
                    scanf("%c",&path[i][j]);
            }
            Del(line,-1);
            tmp1=1,tmp2=1;
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=m;j++)
                {
                    if(path[i][j]=='*')
                    {
                        if((i+j)%2==0)
                            line[i][j]=tmp1++;
                        else
                            line[i][j]=tmp2++;
                    }
                }
            }
    
            Del(map,0);
            for(int i=1; i<=n; i++)
            {
                for(int j=1; j<=m; j++)
                {
                    if(path[i][j]=='*' && (i+j)%2==1)
                    {
                        if(line[i-1][j]>=1)
                            map[line[i-1][j]][line[i][j]]=1;
                        if(line[i+1][j]>=1)
                            map[line[i+1][j]][line[i][j]]=1;
                        if(line[i][j-1]>=1)
                            map[line[i][j-1]][line[i][j]]=1;
                        if(line[i][j+1]>=1)
                            map[line[i][j+1]][line[i][j]]=1;
                    }
                }
            }
            solve();
        }
        return 0;
    }
    


  • 相关阅读:
    表单全选,不选和反选
    利用js改变宽,高等属性
    点击显示与隐藏
    改变div的不同属性
    给三个不同的div变色
    经典排序算法实现
    基本排序算法的实现
    排序的概念及分类实现
    #和##运算符实例
    #pragma预处理实例
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5053755.html
Copyright © 2020-2023  润新知