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;
}
posted @ 2012-07-04 10:27  金海峰  阅读(1129)  评论(2编辑  收藏  举报