给同一张横着的牌的所在的格子编同一样的号,这些格子对应x集合,给同一张竖着的牌所在的格子编同一样的号,对应y集合,同一个格子上既有横着的牌又有竖着的牌,那么就建一条边,有冲突就要拿走一张,结果是总的牌数-最大二分图匹配数···
贴代码:
1 #include <cstdio> 2 #include <cstring> 3 #define N 1100 4 int nx,ny; 5 int cx[N],cy[N]; 6 int g[N][N]; 7 bool vis[N]; 8 int map[N][N]; 9 bool path(int u) 10 { 11 for(int v=0; v<ny; ++v) 12 { 13 if(g[u][v] && !vis[v]) 14 { 15 vis[v] =1; 16 if(cy[v]==-1 || path(cy[v])) 17 { 18 cx[u] = v; 19 cy[v] =u; 20 return true; 21 } 22 } 23 } 24 return false; 25 } 26 int maxMatch() 27 { 28 int ans =0; 29 memset(cx,-1,sizeof(cx)); 30 memset(cy,-1,sizeof(cy)); 31 for(int i=0; i<nx; ++i) 32 { 33 if(cx[i] == -1) 34 { 35 memset(vis,0,sizeof(vis)); 36 if(path(i)) 37 ++ans; 38 } 39 } 40 return ans; 41 } 42 int main() 43 { 44 // freopen("in.c","r",stdin); 45 while(scanf("%d%d",&nx,&ny),nx&&ny) 46 { 47 memset(map,-1,sizeof(map)); 48 int x,y; 49 for(int i=0; i<nx; ++i) 50 { 51 scanf("%d%d",&x,&y); 52 map[x][y] =i; 53 map[x+1][y]= i; 54 } 55 memset(g,0,sizeof(g)); 56 for(int i=0; i<ny; ++i) 57 { 58 scanf("%d%d",&x,&y); 59 if(map[x][y] != -1 ) g[map[x][y]][i] =1; 60 if(map[x][y+1] != -1) g[map[x][y+1]][i] =1; 61 } 62 printf("%d ",nx+ny-maxMatch()); 63 } 64 return 0; 65 }