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 }

 

posted @ 2014-11-04 00:15  Naturain  阅读(156)  评论(0编辑  收藏  举报