zoukankan      html  css  js  c++  java
  • HDU1507 Uncle Tom's Inherited Land* 二分图匹配 匈牙利算法 黑白染色

    原文链接http://www.cnblogs.com/zhouzhendong/p/8254062.html


    题目传送门 - HDU1507


    题意概括

      有一个n*m的棋盘,有些点是废的。

      现在让你用1*2的矩形覆盖所有的不废的点,并且不重叠,问最多可以覆盖多少个1*2的矩形,输出方案,有SPJ。

      输入描述:

      多组数据,每组首先两个数n,m(如果n和m为0,则结束程序)

      然后给出k

      然后给出k个二元组(x,y)表示废点的坐标。


    题解

      按照前两片博文的算法已经不行了,因为方案不对了。

      所以我们要进行黑白染色。

      仅从(x,y)(x+y为奇数)向四连通方向连边,然后二分图匹配即可。

      其中match数组的值就是匹配对象。


    代码

    #include <cstring>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    #include <cstdio>
    using namespace std;
    const int N=105,K=55;
    int dx[4]={ 0, 0,-1, 1};
    int dy[4]={-1, 1, 0, 0};
    int n,m,k,cnt,pl[N][N],tn[N][N],bj[K],x[K],y[K];
    int g[K][K],vis[K],match[K];
    bool check(int x,int y){
    	return 1<=x&&x<=n&&1<=y&&y<=m&&tn[x][y];
    }
    bool Match(int x){
    	for (int i=1;i<=cnt;i++)
    		if (!vis[i]&&g[x][i]){
    			vis[i]=1;
    			if (!match[i]||Match(match[i])){
    				match[i]=x;
    				return 1;
    			}
    		}
    	return 0;
    }
    int hungary(){
    	int res=0;
    	memset(match,0,sizeof match);
    	for (int i=1;i<=cnt;i++){
    		if (!bj[i])
    			continue;
    		memset(vis,0,sizeof vis);
    		if (Match(i))
    			res++;
    	}
    	return res;
    }
    int main(){
    	while (~scanf("%d%d",&n,&m)&&(n||m)){
    		scanf("%d",&k);
    		memset(pl,0,sizeof pl);
    		for (int i=1,x,y;i<=k;i++)
    			scanf("%d%d",&x,&y),pl[x][y]=1;
    		memset(tn,0,sizeof tn);
    		cnt=0;
    		for (int i=1;i<=n;i++)
    			for (int j=1;j<=m;j++)
    				if (!pl[i][j]){
    					bj[tn[i][j]=++cnt]=(i+j)&1;
    					x[cnt]=i,y[cnt]=j;
    				}
    		memset(g,0,sizeof g);
    		for (int i=1;i<=n;i++)
    			for (int j=1;j<=m;j++)
    				if ((i+j)&1)
    					for (int d=0;d<4;d++){
    						int a=i+dx[d],b=j+dy[d];
    						if (check(a,b))
    							g[tn[i][j]][tn[a][b]]=1;
    					}
    		int ans=hungary();
    		printf("%d
    ",ans);
    		for (int i=1;i<=cnt;i++)
    			if (match[i])
    				printf("(%d,%d)--(%d,%d)
    ",x[i],y[i],x[match[i]],y[match[i]]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    SpringBoot多数据库连接(mysql+oracle)
    SOAP与REST API的区别
    我与OAuth 2.0那点荒唐的小秘密
    我与Git的那些破事(下)--分支模型
    我与Git的那些破事(上)--代码管理
    Salesforce学习之路(十三)Aura案例实战分析
    Salesforce学习之路(十二)Aura组件表达式
    react 脚手架初次npm start时候运行报错
    兼容ie 提示用户升级浏览器 <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    一行代码实现网站一键变灰功能
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/HDU1507.html
Copyright © 2011-2022 走看看