POJ 2446 Chessboard 匹配/最小路径覆盖

http://poj.org/problem?id=2446

跟 poj 3020差不多

以前做过一个最小路径覆盖的题,读完这个题就想到了最小路径覆盖。很多大神用的完全匹配,有一点值得学习,就是根据i+j的奇偶性,把点分成两个集合,这样也可以?!

最小路径覆盖的代码(为什么我的运行时间那么长??):

代码:

 

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int a[35][35],link[1500],map[1500][1500];
bool vs[1500];
int n,m,N,M;
bool dfs(int x)
{
    for(int i=1;i<=M;i++)
    {
        if(map[x][i]&&!vs[i])
        {
            vs[i]=1;
            if(!link[i]||dfs(link[i]))
            {
                link[i]=x;
                return 1;
            }
        }
    }
    return 0;
}
int MaxMatch()
{
    int i,cnt=0;
    memset(link,0,sizeof(link));
    for(i=1;i<=N;i++)
    {
        memset(vs,0,sizeof(vs));
        if(dfs(i))cnt++;
    }
    return cnt;
}
int main()
{
   int i,j,k,h;
   while(~scanf("%d%d%d",&n,&m,&k))
   {
       memset(a,-1,sizeof(a));
       for(h=1;h<=k;h++)
       {
           scanf("%d%d",&i,&j);
           a[j][i]=0;//有洞
       }
       if((n*m-k)%2!=0){printf("NO\n");continue;}
       N=0,M=0;
       for(i=1;i<=n;i++)
           for(j=1;j<=m;j++)
           {
             if(a[i][j]==-1)
             {
                 if((i+j)%2==1)
                    a[i][j]=++N; //没有hole的
                else a[i][j]=++M;
             }
           }
       memset(map,0,sizeof(map));
      for(i=1;i<=n;i++)
        for(j=1;j<=m;j++)
        {
             if(a[i][j]<1||(i+j)%2==0)continue;
             if(a[i-1][j]>=1)
                map[a[i][j]][a[i-1][j]]=1;
             if(a[i+1][j]>=1)
                map[a[i][j]][a[i+1][j]]=1;
             if(a[i][j-1]>=1)
                map[a[i][j]][a[i][j-1]]=1;
             if(a[i][j+1]>=1)
                map[a[i][j]][a[i][j+1]]=1;
        }
      int ans=MaxMatch();//最大匹配
      if(ans==(n*m-k)/2)printf("YES\n");
      else printf("NO\n");
   }
   return 0;
}

 

  

 

posted @ 2012-02-21 00:02  快乐.  阅读(191)  评论(0编辑  收藏  举报