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\n",++cas,ans);
	}
	return 0;
}

  

posted @ 2016-05-07 18:18  20143605  阅读(233)  评论(0编辑  收藏  举报