zoukankan      html  css  js  c++  java
  • UVALive-7303 Aquarium (最小生成树)

    题目大意:在nxm的方格中,每一个1x1的小方格中都有一堵沿对角线的墙,并且每堵墙都有一个坚固程度,这些墙将nxm的方格分割成了若干个区域。现在要拆除一些墙,使其变成一个区域。

    题目分析:将区域视作点,将墙视作边,这样问题就变成了求最小生成树。

    代码如下:

    # include<iostream>
    # include<cstdio>
    # include<cmath>
    # include<vector>
    # include<list>
    # include<queue>
    # include<cstring>
    # include<algorithm>
    using namespace std;
    # define LL long long
    
    const int INF=1000000000;
    const int N=1000;
    const double eps=1e-10;
    const double inf=1e20;
    
    int n,m;
    char p[105][105];
    int a[105][105];
    int vis[105][105][2];
    
    struct Edge
    {
    	int fr,to,w;
    	bool operator < (const Edge &a) const{
    		return w<a.w;
    	}
    };
    Edge e[20000];
    int fa[20000];
    
    bool ok(int x,int y)
    {
    	return x>=0&&x<n&&y>=0&&y<m;
    }
    
    void dfs(int x,int y,int f,int cnt)
    {
    	vis[x][y][f]=cnt;
    	if(p[x][y]=='\'){
    		if(f==1){
    			if(ok(x,y-1)){
    				if(p[x][y-1]=='\'&&vis[x][y-1][0]==-1) dfs(x,y-1,0,cnt);
    				if(p[x][y-1]=='/'&&vis[x][y-1][1]==-1) dfs(x,y-1,1,cnt);
    			}
    			if(ok(x+1,y)&&vis[x+1][y][0]==-1)
    				dfs(x+1,y,0,cnt);
    		}else{
    			if(ok(x-1,y)&&vis[x-1][y][1]==-1)
    				dfs(x-1,y,1,cnt);
    			if(ok(x,y+1)){
    				if(p[x][y+1]=='\'&&vis[x][y+1][1]==-1) dfs(x,y+1,1,cnt);
    				if(p[x][y+1]=='/'&&vis[x][y+1][0]==-1) dfs(x,y+1,0,cnt);
    			}
    		}
    	}else{
    		if(f==1){
    			if(ok(x,y+1)){
    				if(p[x][y+1]=='\'&&vis[x][y+1][1]==-1) dfs(x,y+1,1,cnt);
    				if(p[x][y+1]=='/'&&vis[x][y+1][0]==-1) dfs(x,y+1,0,cnt);
    			}
    			if(ok(x+1,y)&&vis[x+1][y][0]==-1)
    				dfs(x+1,y,0,cnt);
    		}else{
    			if(ok(x-1,y)&&vis[x-1][y][1]==-1)
    				dfs(x-1,y,1,cnt);
    			if(ok(x,y-1)){
    				if(p[x][y-1]=='\'&&vis[x][y-1][0]==-1) dfs(x,y-1,0,cnt);
    				if(p[x][y-1]=='/'&&vis[x][y-1][1]==-1) dfs(x,y-1,1,cnt);
    			}
    		}
    	}
    }
    
    int find_fa(int x)
    {
    	int u=x;
    	while(fa[u]!=u)
    		u=fa[u];
    	while(fa[x]!=u){
    		int t=x;
    		x=fa[x];
    		fa[t]=u;
    	}
    	return u;
    }
    
    int main()
    {
    	int T;
    	scanf("%d",&T);
    	int cas=0;
    	while(T--)
    	{
    		scanf("%d%d",&n,&m);
    		memset(vis,-1,sizeof(vis));
    		for(int i=0;i<n;++i)
    			scanf("%s",p[i]);
    		for(int i=0;i<n;++i)
    			for(int j=0;j<m;++j)
    				scanf("%d",&a[i][j]);
    		int cnt=0;
    		for(int i=0;i<n;++i){
    			for(int j=0;j<m;++j){
    				if(vis[i][j][0]==-1){
    					dfs(i,j,0,cnt);
    					++cnt;
    				}
    				if(vis[i][j][1]==-1){
    					dfs(i,j,1,cnt);
    					++cnt;
    				}
    			}
    		}
    		int k=0;
    		for(int i=0;i<n;++i){
    			for(int j=0;j<m;++j){
    				if(vis[i][j][0]==vis[i][j][1]) continue;
    				e[k].fr=vis[i][j][0];
    				e[k].to=vis[i][j][1];
    				e[k].w=a[i][j];
    				++k;
    			}
    		}
    		sort(e,e+k);
    		for(int i=0;i<cnt;++i)
    			fa[i]=i;
    		int ans=0;
    		for(int i=0;i<k;++i){
    			int f1=find_fa(e[i].fr);
    			int f2=find_fa(e[i].to);
    			if(f1!=f2){
    				ans+=e[i].w;
    				fa[f1]=f2;
    			}
    		}
    		printf("Case %d: %d
    ",++cas,ans);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    java设计模式之建造者模式
    java设计模式之工厂模式
    Java并发—简介与线程创建
    Java基础—反射(转载)
    Eclipse中svn操作
    js常用方法总结
    Oracle学习笔记—常用函数
    Oracle学习笔记—connect、resource和dba三种权限(转载)
    JavaWeb—拦截器Interceptor
    JavaWeb—监听器Listener
  • 原文地址:https://www.cnblogs.com/20143605--pcx/p/5468882.html
Copyright © 2011-2022 走看看