zoukankan      html  css  js  c++  java
  • poj2226

    题意:给定一个矩阵,其中有一些地方有水,用一些长度任意,宽度为1的木板盖住这些有水的地方,问至少需要几块板子。

    分析:二分图最小点集覆盖。二分图建图方法如下,把每段连续的横向的水洼看成是一个X集合中的点,每段连续的纵向的水洼看成是Y集合中的点。矩阵每个有水单元看成是一个边,它连接了它所在的横向水洼在X集合中对应的点和它所在的纵向水洼在Y集合中对应的点。(对于一段连续的水洼,如果要铺木板,一定要铺得尽量长)这样最小点集覆盖的意义就变成了,矩阵中的每个有水的单元(二分图中的每条边)所在的横向和纵向的水洼(在X集合和Y集合中的两个端点)至少有一个被覆盖。求至少需要选几个点。

    View Code
    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    using namespace std;
    
    #define maxr 55
    #define maxc 55
    #define maxx maxr * maxc / 2
    #define maxy maxx
    
    struct Edge
    {
        int x, y;
    }edge[maxr][maxc];
    
    int row, column;
    char map[maxr][maxc];
    int xcount, ycount;
    bool visit[maxy];
    int match[maxy];
    bool g[maxx][maxy];
    
    void input()
    {
        scanf("%d%d", &row, &column);
        for (int i = 0; i < row; i++)
            scanf("%s", map[i]);
    }
    
    void make()
    {
        xcount = 0;
        ycount = 0;
        for (int i = 0; i < row; i++)
        {
            int j = 0;
            while (j < column)
            {
                while (j < column && map[i][j] == '.')
                    j++;
                if (j >= column)
                    break;
                while (j < column && map[i][j] == '*')
                {
                    edge[i][j].x = xcount;
                    j++;
                }
                xcount++;
            }
        }
    
        for (int i = 0; i < column; i++)
        {
            int j = 0;
            while (j < row)
            {
                while (j < row && map[j][i] == '.')
                    j++;
                if (j >= row)
                    break;
                while (j < row && map[j][i] == '*')
                {
                    edge[j][i].y = ycount;
                    j++;
                }
                ycount++;
            }
        }
    
        for (int i = 0; i < row; i++)
            for (int j = 0; j < column; j++)
                if (map[i][j] == '*')
                {
                    //printf("%d %d\n", edge[i][j].x, edge[i][j].y);
                    g[edge[i][j].x][edge[i][j].y] = true;
                }
    }
    
    bool dfs(int k)
    {
        int t;
        for (int i = 0; i < ycount; i++)
        {
            if (g[k][i] && !visit[i])
            {
                visit[i] = true;
                t = match[i];
                match[i] = k;
                if (t == -1 || dfs(t))
                    return true;
                match[i] = t;
            }
        }
        return false;
    }
    
    int max_match()
    {
        int ans = 0;
        for (int i = 0; i < xcount; i++)
        {
            memset(visit, false, sizeof(visit));
            if (dfs(i))
                ans ++;
        }
        return ans;
    }
    
    int main()
    {
        //freopen("t.txt", "r", stdin);
        memset(g, 0, sizeof(g));
        input();
        make();
        memset(match, -1, sizeof(match));
        printf("%d\n", max_match());
        return 0;
    }
  • 相关阅读:
    JDBC 复习4 批量执行SQL
    JDBC 复习3 存取Oracle大数据 clob blob
    Oracle复习
    Linux命令(1)grep
    JDBC 复习2 存取mysql 大数据
    JDBC 复习1 DBUtil
    php 环境搭建问题
    Windows 批处理 bat 开启 WiFi 菜单选项 设置ID PWD
    Bat 批处理启动和停止Oracle 服务
    docker 学习1 WSL docker ,Windows docker
  • 原文地址:https://www.cnblogs.com/rainydays/p/2575794.html
Copyright © 2011-2022 走看看