您的位置:首页 > 其它

UVALive 7303 Aquarium 最小生成树

2017-04-30 09:58 316 查看
题意:给定一个n*m的方格,每个方格都由'/'或'\'来分隔成两个部分,假设他们是一堵墙,有它的坚硬程度,
现在需要打破其中一些墙,来使得每个格子都连通,并且所需的坚硬值最小。

思路:连通性问题并要求权值最小,那就是最小生成树的问题了,建图,因为每个格子都分隔成两个部分,所以
  所以给这两个部分编号,墙壁的坚硬值就是连接这两部分的权值,再分类讨论一下,这两部分与其周围相邻

          部分的联通情况,权值为0,仔细考虑就不会写错,为了方便表示,规定每个格子的上半部分比下半部分的编

         号小1,最后来一遍最小生成树就可以了。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <vector>
#include <map>
#include <cmath>
#include <set>
#include <queue>
using namespace std;

const int INF=1e9+10;
const double EPS = 1e-10;
typedef long long ll;
int v[105][105],cnt[105][105];
char mp[105][105];
struct edge{
int u,v,cost;
};
bool cmp(edge a,edge b){
return a.cost<b.cost;
}

edge es[100000];
int par[200050];
void init(int n){
for(int i=0;i<=n;i++){
par[i]=i;
}
}

int find(int x){
if(par[x]==x)
return x;
else
return par[x]=find(par[x]);
}

void unite(int x,int y){
x=find(x);
y=find(y);
if(x!=y)
par[x]=y;
}

bool same(int x,int y){
return find(x)==find(y);
}

ll solve(int n,int k){
init(n);
ll res=0;
sort(es,es+k,cmp);
for(int i=0;i<k;i++){
edge e=es[i];
if(!same(e.u,e.v)){
unite(e.u,e.v);
res+=1LL*e.cost;
}
}
return res;
}
int main(){
//freopen("out.txt","w",stdout);
int t;
scanf("%d",&t);
int cas=1;
while(t--){
int n,m;
scanf("%d %d",&n,&m);
for(int i=0;i<n;i++){
scanf("%s",mp[i]);
}
int k=0;
for(int i=0;i<n;i++)
for(int j=0;j<m;j++){
scanf("%d",&v[i][j]);
cnt[i][j]=k;
k+=2;
}
int mxnode=k-1;
k=0;
for(int i=0;i<n;i++){
for(int j=0;j<m;j++){
int a=cnt[i][j];
int b=a+1;
es[k++]=(edge){a,b,v[i][j]};
if(mp[i][j]=='/'){
int x1=i-1,y1=j-1;
if(x1>=0){
es[k++]=(edge){a,cnt[x1][j]+1,0};
}
if(y1>=0){
if(mp[i][y1]=='/')
es[k++]=(edge){a,cnt[i][y1]+1,0};
else
es[k++]=(edge){a,cnt[i][y1],0};
}
x1=i+1,y1=j+1;
if(x1<n){
es[k++]=(edge){b,cnt[x1][j],0};
}
if(y1<m){
if(mp[i][y1]=='/')
es[k++]=(edge){b,cnt[i][y1],0};
else
es[k++]=(edge){b,cnt[i][y1]+1,0};
}

}
else{
int x1=i-1,y1=j+1;
if(x1>=0){
es[k++]=(edge){a,cnt[x1][j]+1,0};
}
if(y1<m){
if(mp[i][y1]=='/')
es[k++]=(edge){a,cnt[i][y1],0};
else
es[k++]=(edge){a,cnt[i][y1]+1,0};
}
x1=i+1,y1=j-1;
if(x1<n){
es[k++]=(edge){b,cnt[x1][j],0};
}
if(y1>=0){
if(mp[i][y1]=='/')
es[k++]=(edge){b,cnt[i][y1]+1,0};
else
es[k++]=(edge){b,cnt[i][y1],0};
}
}
}
}
ll ans=solve(mxnode,k);
//printf("Case %d: %lld\n",cas++,ans );
cout<<"Case "<<cas++<<": "<<ans<<endl;
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: