Poj--2446(二分图最大匹配)
2014-11-04 00:03:08
思路:建图比较巧妙~,除了洞之外,给每个点进行编号,然后根据相邻关系进行建边,然后让两个均包含所有点的集合进行匹配,发现:一条匹配边实际上就是一个1×2的矩形,然后就是二分图最大匹配了。
1 /************************************************************************* 2 > File Name: 2446.cpp 3 > Author: Nature 4 > Mail: 564374850@qq.com 5 > Created Time: Mon 03 Nov 2014 11:20:33 PM CST 6 ************************************************************************/ 7 8 #include <cstdio> 9 #include <cstring> 10 #include <cstdlib> 11 #include <cmath> 12 #include <vector> 13 #include <map> 14 #include <set> 15 #include <stack> 16 #include <queue> 17 #include <iostream> 18 #include <algorithm> 19 using namespace std; 20 #define lp (p << 1) 21 #define rp (p << 1|1) 22 #define getmid(l,r) (l + (r - l) / 2) 23 #define MP(a,b) make_pair(a,b) 24 typedef long long ll; 25 const int INF = 1 << 30; 26 const int maxn = 1100; 27 28 int n,m,k,id; 29 int first[maxn],next[maxn << 2],ver[maxn << 2],ecnt; 30 int g[50][50]; 31 int dir[4][2] = {{-1,0},{1,0},{0,-1},{0,1}}; 32 int used[maxn],mat[maxn]; 33 34 void Init(){ 35 memset(g,0,sizeof(g)); 36 memset(first,-1,sizeof(first)); 37 ecnt = id = 0; 38 } 39 40 void Add_edge(int u,int v){ 41 next[++ecnt] = first[u]; 42 ver[ecnt] = v; 43 first[u] = ecnt; 44 } 45 46 void Build_graph(){ 47 for(int i = 1; i <= m; ++i){ 48 for(int j = 1; j <= n; ++j) if(g[i][j] != -1){ 49 for(int o = 0; o < 4; ++o){ 50 int ti = i + dir[o][0]; 51 int tj = j + dir[o][1]; 52 if(ti >= 1 && ti <= m && tj >= 1 && tj <= n && g[ti][tj] != -1) 53 Add_edge(g[i][j],g[ti][tj]); 54 } 55 } 56 } 57 } 58 59 bool find(int p){ 60 for(int i = first[p]; i != -1; i = next[i]){ 61 int v = ver[i]; 62 if(used[v] == 0){ //不在增广路中 63 used[v] = 1; 64 if(mat[v] == 0 || find(mat[v])){ 65 //该点是未盖点或者从该点出发能到达未盖点 66 mat[v] = p; 67 return true; 68 } 69 } 70 } 71 return false; 72 } 73 74 bool Hungary(){ 75 memset(mat,0,sizeof(mat)); 76 int ans = 0; 77 for(int i = 1; i <= id; ++i){ 78 memset(used,0,sizeof(used)); 79 if(find(i)) ans++; 80 } 81 if(ans == id) return true; 82 return false; 83 } 84 85 int main(){ 86 int a,b; 87 while(scanf("%d%d%d",&m,&n,&k) != EOF){ 88 Init(); 89 for(int i = 1; i <= k; ++i){ 90 scanf("%d%d",&a,&b); 91 g[b][a] = -1; 92 } 93 if((n * m % 2) != (k % 2)){ 94 printf("NO\n"); 95 continue; 96 } 97 for(int i = 1; i <= m; ++i){ 98 for(int j = 1; j <= n; ++j){ 99 if(g[i][j] != -1) 100 g[i][j] = ++id; 101 } 102 } 103 Build_graph(); 104 if(Hungary()) 105 printf("YES\n"); 106 else 107 printf("NO\n"); 108 } 109 return 0; 110 }