codevs 1022 覆盖
题目链接:http://codevs.cn/problem/1022/
题解:
匈牙利稍作改动,用邻接矩阵存储,以{横坐标和纵坐标都为奇数或横坐标和纵坐标都为偶数的点}为一个子集,其余的点为另一个子集,每次枚举4个方向进行深搜
1 #include<cstdio> 2 #include<cstring> 3 #define MAXN 110 4 int n,m,k,edge[MAXN][MAXN][2],ans; 5 bool used[MAXN][MAXN],map[MAXN][MAXN],wat[MAXN][MAXN]; 6 int _1[]={0,0,0,-1,1},_2[]={0,1,-1,0,0};//记录四个方向 7 bool dfs(int x,int y) 8 { 9 for(int i=1;i<=4;i++) 10 { 11 int xi=x+_1[i],yi=y+_2[i];//v的横纵坐标 12 if(xi>n||yi>m||xi<1||yi<1)continue;//出界 13 if(wat[xi][yi]||map[xi][yi]||used[xi][yi])continue; 14 used[xi][yi]=true; 15 if(!edge[xi][yi][0]||dfs(edge[xi][yi][0],edge[xi][yi][1])) 16 { 17 edge[xi][yi][0]=x;edge[xi][yi][1]=y;//更新match 18 return true; 19 } 20 } 21 return false; 22 } 23 int main() 24 { 25 scanf("%d%d",&n,&m); 26 scanf("%d",&k); 27 for(int i=1;i<=k;i++) 28 { 29 int t1,t2; 30 scanf("%d%d",&t1,&t2); 31 wat[t1][t2]=true;//判断是否是水格 32 } 33 for(int i=1;i<=n;i++) 34 { 35 for(int j=1;j<=m;j++) 36 { 37 if(wat[i][j])continue; 38 else if(i%2==j%2)map[i][j]=true;//分子集 39 } 40 } 41 for(int i=1;i<=n;i++) 42 { 43 for(int j=1;j<=m;j++) 44 { 45 if(!wat[i][j]&&map[i][j]) 46 { 47 memset(used,false,sizeof(used)); 48 if(dfs(i,j))ans++; 49 } 50 } 51 } 52 printf("%d\n",ans); 53 return 0; 54 }