POJ 2226 Muddy Fields【二分图最小点覆盖】

题意: 给你一个农场 例如

*.*.
.***
***.
..*.
其中 *代表障碍物, . 代表空地,你可以用宽度为1 长度不限的木板去覆盖这些障碍,木块可以重叠,问你最少需要多少木块

    可以把所有 * 覆盖掉。

分析: 二分图最小点权覆盖,这道题建图比较特别,之前的 POJ 3041 是一次覆盖一行或一列,可以 把行看成 X集合, 把列看成是 Y 集合,进行二分图匹配,但是这题每一行或每一列的

   障碍物可能是不连续的, 所以要把同一行的各个连续的障碍段分开进行建图,可以把每一行或每一列连续的一段标记成同一个序号,每一个点看成是行这一段的障碍和列这一段障碍的边,

    建立关系,最后求出最大匹配即最小覆盖。

View Code
#include<stdio.h>
#include<string.h>
#define clr(x)memset(x,0,sizeof(x))
struct node
{
    int to,next;
}q[100000];
int head[300];
int tot;
int link[1000];
int v[1000];
void add(int s,int u)
{
    q[tot].to=u;
    q[tot].next=head[s];
    head[s]=tot++;
}
int a[3000];
int b[3000];
int vis[55][55];
char map[55][55];
int ma[55][55];
int mb[55][55];
int find(int x)
{
    int k,i;
    for(i=head[x];i;i=q[i].next)
    {
        k=q[i].to;
        if(!v[k])
        {
            v[k]=1;
            if(link[k]==0||find(link[k]))
            {
                link[k]=x;
                return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int an,bn,n,m,i,sum,j,k,x;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        clr(link);
        clr(head);
        tot=1;
        for(i=1;i<=n;i++)
            scanf("%s",map[i]+1);
        x=1;
        an=bn=0;
        clr(vis);
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                if(!vis[i][j]&&map[i][j]=='*')
                {
                   a[an++]=x;
                   for(k=j;k<=m;k++)
                   {
                       if(map[i][k]=='*'){
                            vis[i][k]=1;
                            ma[i][k]=x;
                       }
                       else break;
                   }
                   x++;
                }
        clr(vis);
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                if(!vis[i][j]&&map[i][j]=='*')
                {
                    b[bn++]=x;
                    for(k=i;k<=n;k++)
                    {
                        if(map[k][j]=='*'){
                            vis[k][j]=1;
                            mb[k][j]=x;
                        }
                        else break;
                    }
                    x++;
                }
        for(i=1;i<=n;i++)
            for(j=1;j<=m;j++)
                if(map[i][j]=='*')
                    add(ma[i][j],mb[i][j]);
        sum=0;
        for(i=0;i<an;i++)
        {
            clr(v);
            if(find(a[i]))
                sum++;
        }
        printf("%d\n",sum);
    }
    return 0;
}

 

 

posted @ 2012-04-23 20:00  'wind  阅读(177)  评论(0编辑  收藏  举报