HDU 1507 Uncle Tom's Inherited Land(最大匹配+分奇偶部分)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1507

题目大意:给你一张n*m大小的图,可以将白色正方形凑成1*2的长方形,问你最多可以凑出几块,并输出任一组匹配方案。

解题思路:按行列和奇偶划分两个集合,从而得到二分图,然后进行最大匹配,根据link数组的匹配结果输出相应匹配即可。

代码:

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 #include<algorithm>
  6 using namespace std;
  7 const int N=1e2+5;
  8 
  9 int n,m,cnt,idx;
 10 int mp[N][N],link[N],head[N];
 11 bool vis[N];
 12 int d[4][2]={0,1,1,0,-1,0,0,-1};
 13 
 14 struct node{
 15     int x,y;
 16     node(){}
 17     node(int x,int y):x(x),y(y){}
 18 }a[N*N];
 19 
 20 struct enode{
 21     int to,next;
 22 }edge[N*N];
 23 
 24 void init(){
 25     cnt=0;
 26     idx=1;
 27     memset(mp,0,sizeof(mp));
 28     memset(head,0,sizeof(head));
 29 }
 30 
 31 void addedge(int u,int v){
 32     edge[idx].to=v;
 33     edge[idx].next=head[u];
 34     head[u]=idx++;
 35 }
 36 
 37 bool dfs(int u){
 38     for(int i=head[u];i;i=edge[i].next){
 39         int t=edge[i].to;
 40         if(!vis[t]){
 41             vis[t]=true;
 42             if(link[t]==-1||dfs(link[t])){
 43                 link[t]=u;
 44                 return true;
 45             }
 46         }
 47     }
 48     return false;
 49 }
 50 
 51 int max_match(){
 52     memset(link,-1,sizeof(link));
 53     int ans=0;
 54     for(int i=1;i<=cnt;i++){
 55         memset(vis,false,sizeof(vis));
 56         if(dfs(i)) ans++;
 57     }
 58     return ans;
 59 }
 60 
 61 int main(){
 62     while(~scanf("%d%d",&n,&m)&&n&&m){
 63         init();
 64         int k;
 65         scanf("%d",&k);
 66         for(int i=1;i<=k;i++){
 67             int x,y;
 68             scanf("%d%d",&x,&y);
 69             mp[x][y]=-1;
 70         }
 71         for(int i=1;i<=n;i++){
 72             for(int j=1;j<=m;j++){
 73                 if(mp[i][j]!=-1){
 74                     mp[i][j]=++cnt;
 75                     a[cnt]=node(i,j);
 76                 }
 77             }
 78         }
 79         for(int i=1;i<=n;i++){
 80             for(int j=1;j<=m;j++){
 81                 //加了(i+j)%2这句分奇偶就对了,不知道为什么不分会错。。。。
 82                 if(mp[i][j]!=-1&&(i+j)%2==1){
 83                     for(int k=0;k<4;k++){
 84                         int x=i+d[k][0];
 85                         int y=j+d[k][1];
 86                         if(x<=0||y<=0||x>n||y>m||mp[x][y]==-1) continue;
 87                         addedge(mp[i][j],mp[x][y]);
 88                     }
 89                 }
 90             }
 91         }
 92         printf("%d\n",max_match());
 93         vector<node>ans;
 94         for(int i=1;i<=cnt;i++){
 95             if(link[i]!=-1){
 96                 ans.push_back(node(i,link[i]));
 97                 link[i]=link[link[i]]=-1;
 98             }
 99         }
100         for(int i=0;i<ans.size();i++){
101             int p1=ans[i].x,p2=ans[i].y;
102             printf("(%d,%d)--(%d,%d)\n",a[p1].x,a[p1].y,a[p2].x,a[p2].y);
103         }
104         printf("\n");
105     }
106     return 0;
107 }

 

posted @ 2018-04-11 00:58  Yeader  阅读(144)  评论(0编辑  收藏  举报