zoukankan      html  css  js  c++  java
  • POJ1469 COURSES 二分图匹配 匈牙利算法

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


    题目传送门 - POJ1469


    题意概括

      在一个大矩阵中,有一些障碍点。

      现在让你用1*2的小矩形覆盖非障碍点,要求不覆盖到障碍点并且不重复覆盖,问是否可以覆盖所有非障碍点。


    题解

      本题几乎是裸题。

      首先注意读入的表示障碍点的二元组(x,y)中y是行,x是列。

      这个毒性深重<差评>

     

      然后考虑算法。读者可以参考笔者的前一篇博客。

      对于相邻的非障碍点我们来回都建边。然后我们给原图按照到某一个点的曼哈顿距离的奇偶性黑白染色,发现黑的只能连向白的,白的也只可以连向黑的。于是这就是一个二分图。

      然后我们跑一炮匈牙利。

      由于连出的边是来回的,所以相当于重复计算了一次,即最大匹配数翻倍了。

      于是就恰好变成了覆盖非障碍点的最大数。直接和障碍点的总数比较即可。

      注意本题用二维数组存图会TLE(我会TLE),改成数组模拟链表就过去了。<差评++>


    代码

    #include <cstring>
    #include <cstdio>
    #include <cstdlib>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    const int N=35,K=1100;
    struct Gragh{
    	int cnt,y[K*4],nxt[K*4],fst[K];
    	void clear(){
    		cnt=0;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b){
    		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    int m,n,k,cnt,pl[N][N],tn[N][N],match[K],vis[K];
    bool check(int x,int y){
    	return 1<=x&&x<=m&&1<=y&&y<=n&&!pl[x][y];
    }
    bool Match(int x){
    	for (int i=g.fst[x];i;i=g.nxt[i]){
    		int y=g.y[i];
    		if (!vis[y]){
    			vis[y]=1;
    			if (!match[y]||Match(match[y])){
    				match[y]=x;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int hungary(){
    	int res=0;
    	memset(match,0,sizeof match);
    	for (int i=1;i<=cnt;i++){
    		memset(vis,0,sizeof vis);
    		if (Match(i))
    			res++;
    	}
    	return res;
    }
    int main(){
    	while (~scanf("%d%d%d",&m,&n,&k)){
    		memset(pl,0,sizeof pl);
    		memset(tn,0,sizeof tn);
    		for (int i=1,a,b;i<=k;i++)
    			scanf("%d%d",&b,&a),pl[a][b]=1;
    		cnt=0;
    		for (int i=1;i<=m;i++)
    			for (int j=1;j<=n;j++)
    				if (!pl[i][j])
    					tn[i][j]=++cnt;
    		g.clear();
    		for (int i=1;i<=m;i++)
    			for (int j=1;j<=n;j++){
    				if (pl[i][j])
    					continue;
    				if (check(i,j-1))
    					g.add(tn[i][j],tn[i][j-1]);
    				if (check(i,j+1))
    					g.add(tn[i][j],tn[i][j+1]);
    				if (check(i-1,j))
    					g.add(tn[i][j],tn[i-1][j]);
    				if (check(i+1,j))
    					g.add(tn[i][j],tn[i+1][j]);
    			}
    		puts((hungary()==cnt)?"YES":"NO");
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    JSP基本使用
    Web介绍
    通用的数据库数据操作类
    Java集合与泛型
    我是如何刷 LeetCode
    这或许是东半球讲十大排序算法最好的一篇文章(c++版程序)
    【游戏后端】游戏服务器端开发的一些建议(转载)
    【高并发】Redis为什么是单线程,高并发快的3大原因详解
    【高可用】Redis哨兵、复制、集群的设计原理与区别
    深入理解各种排序的一些思路及分享
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/POJ1469.html
Copyright © 2011-2022 走看看