zoukankan      html  css  js  c++  java
  • POJ 2226 Muddy Fields

    本来想着是分别求各个连通图的最小点覆盖,总感觉是正确的却WA,看了别人的解题报告,有点不懈,更不明白自己的想法为什么错呢、、最终由试了一个例子,发现我真的错了!

    *.*.|.
    .***|*
    ***.|*
    ..*.|*

    这个例子按照上边的思想答案仍是4,可惜不是4!发现漏洞了吧!所以说那样做是错的!
    解题思路:
    1.分别以行、列来用木板进行覆盖---依次编号
    2.连接所有交叉的木板即连接覆盖同一污点的木板
    3.求最大匹配==最小点覆盖数

    我对该二分图的理解:
    左右的点解对应着木板(行和列),而边对应着每一个污点,任一个污点都可以用行上或者列上的木板覆盖,所以求覆盖所有边的最少的点即为答案!

    View Code
    #include <stdio.h>
    #include <memory.h>
    
    #define N 1250
    #define M 2500
    
    typedef struct _Data
    {
        int r,c;
    }Data;
    
    Data number[52][52];
    char map[52][52];
    int nodevp[N],nodeu[M],next[M],ind;
    int R,C,num;
    
    void addedge(int v,int u)
    {
        nodeu[ind]=u;
        next[ind]=nodevp[v];
        nodevp[v]=ind++;
    }
    
    
    void buildGraph()
    {
        int i,j,curNum;
    
    //    for(i=0;i<52;i++)    number[0][i]=number[i][0]=1;
        
        curNum=1;
        for(i=1;i<=R;i++)
        {
            for(j=1;j<=C;j++)
                if(map[i][j]=='*')
                {
                    if(map[i][j-1]=='*')
                        number[i][j].r=curNum;
                    else
                        number[i][j].r=++curNum;
                }
            ++curNum;
        }    
        num=curNum;
    
        curNum=1;
        for(i=1;i<=C;i++)
        {
            for(j=1;j<=R;j++)
                if(map[j][i]=='*')
                {
                    if(map[j-1][i]=='*')
                        number[j][i].c=curNum;
                    else
                        number[j][i].c=++curNum;
                }
            ++curNum;
        }
    
        memset(nodevp,-1,sizeof(nodevp)); ind=0;
        for(i=1;i<=R;i++)
            for(j=1;j<=C;j++)
                if(number[i][j].r!=0)
                    addedge(number[i][j].r,number[i][j].c);
    
    }
    
    int flag[N],pre[N];
    int match(int v)
    {
        int i,u;
        for(i=nodevp[v];~i;i=next[i])
        {
            u=nodeu[i];
            if(!flag[u])
            {
                if(pre[u]==-1 || (flag[u]=1,match(pre[u])) )
                {
                    pre[u]=v;
                    return 1;
                }
            }
        }
        return 0;
    }
    
    void solve()
    {
        int i,ans=0;
    
        scanf("%d %d",&R,&C);
        
        for(i=0;i<52;i++)    map[0][i]=map[i][0]='*';
        for(i=1;i<=R;i++)    scanf("%s",map[i]+1);
    
        buildGraph();
    
        memset(pre,-1,sizeof(pre));
        for(i=1;i<=num;i++)    
        {
            memset(flag,0,sizeof(flag));
            ans+=match(i);
        }
    
        printf("%d\n",ans);
    }
    
    
    int main()
    {
    //    freopen("input.txt","r",stdin);
        
        solve();
    
        return 0;
    }



  • 相关阅读:
    系统调用与库函数
    在树莓派上 搭建sqlite数据库
    (转)inux Read系统调用
    查看当前日期是这一年的第几天
    求解某个范围内的全部完数
    求s=a+aa+aaa+aaaa+aa...a的值,其中a是一个数字。
    输入三个整数x,y,z,请把这三个数据由大到小输出。
    模仿ArrayList底层实现
    可视化日历
    Oracle之约束条件1:主键约束
  • 原文地址:https://www.cnblogs.com/fornever/p/2461313.html
Copyright © 2011-2022 走看看