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; }