zoukankan      html  css  js  c++  java
  • 二分图之最小边覆盖(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;
    }
    


  • 相关阅读:
    HomeBrew安装MongoDB如何启动
    Express + Mongoose 极简入门
    Express + Mongoose 极简入门
    浅谈 PHP 与手机 APP 开发(API 接口开发)
    浅谈 PHP 与手机 APP 开发(API 接口开发)
    统计与分布之伯努利分布与二项分布
    统计分布之泊松分布
    统计与分布之高斯分布
    Python 2 和 3 的区别及兼容技巧
    组合与排列
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5053755.html
Copyright © 2011-2022 走看看