• POJ [P3020] Antenna Placement


    二分图匹配求最小边覆盖

    建图方法中的黑白染色法,题目中说信号可以覆盖相邻两个块,那么我们可以将给定的地图染成国际象棋棋盘的样子,一个黑格可以与周围的四个白格共用信号,对于城市,从每一个黑格出发,向其周围的白格连边,那么这就是一个二分图,我们的把城市抽象成了点,所以我们的目的是找到最少的边覆盖所有的点,即最小边覆盖。
    在二分图中,最小边覆盖=顶点数-最大匹配数。

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <algorithm>
    using namespace std;
    int init(){
    	int rv=0,fh=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-') fh=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9'){
    		rv=(rv<<1)+(rv<<3)+c-'0';
    		c=getchar();
    	}
    	return fh*rv;
    }
    int T,n,m,g[405][5],rs[50][50],clr[50][50],dx[4]={-1,0,0,1},dy[4]={0,-1,1,0},match[405];
    bool f[405];
    char ma[50][50];
    bool hungarian(int u){
    	for(int i=1;i<=g[u][0];i++){
    		int v=g[u][i];
    		if(!f[v]){
    			f[v]=1;
    			if(!match[v]||hungarian(match[v])){
    				match[v]=u;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    int main(){
    	T=init();
    	while(T--){
    		n=init();m=init();
    		memset(ma,0,sizeof(ma));
    		memset(rs,0,sizeof(rs));
    		memset(clr,0,sizeof(clr));
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=m;j++){
    				if(j==1) rs[i][j]=!rs[i-1][j];
    				else rs[i][j]=!rs[i][j-1];
    				scanf(" %c ",&ma[i][j]);
    			}
    		}
    		int blk=0,wit=0;
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=m;j++){
    				if(ma[i][j]=='*'){
    					if(rs[i][j]) clr[i][j]=++wit;
    					else clr[i][j]=++blk;
    				}else clr[i][j]=0;
    			}
    		}
    		memset(g,0,sizeof(g));
    		memset(match,0,sizeof(match));
    		for(int i=1;i<=n;i++){
    			for(int j=1;j<=m;j++){
    				if(clr[i][j]&&rs[i][j]){
    					int u=clr[i][j];
    					for(int k=0;k<=3;k++){
    						int x=i+dx[k],y=j+dy[k];
    						if(clr[x][y]) g[u][++g[u][0]]=clr[x][y];
    					}
    				}
    			}
    		}
    		int ans=0;
    		for(int i=1;i<=wit;i++){
    			memset(f,0,sizeof(f));
    			if(hungarian(i)) ans++;
    		}
    		cout<<wit+blk-ans<<endl;
    		//cout<<ans<<endl;
    	}
    }
    
  • 相关阅读:
    从a文件判断是否删除b文件中的行(sed示例)
    绝对路径的表示方式为什么是"/usr"而不是"//usr"
    判断ssh远程命令是否执行结束
    彻底搞懂shell的高级I/O重定向
    Resource Agent:LSB和OCF
    流程控制语句(MySQL/MariaDB )
    MySQL/MariaDB中游标的使用
    翻译:DECLARE HANDLER语句(已提交到MariaDB官方手册)
    从集合的无序性看待关系型数据库中的"序"
    MariaDB/MySQL存储过程和函数
  • 原文地址:https://www.cnblogs.com/Mr-WolframsMgcBox/p/8277458.html
Copyright © 2020-2023  润新知