题目大意:在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; }
时间: 2024-10-12 16:07:40