codevs 1002 搭桥

题目描述 Description
有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点相联系,则它们属于同一座建筑物。现在想在这些建筑物之间搭建一些桥梁,其中桥梁只能沿着矩形的方格的边沿搭建,如下图城市1有5栋建筑物,可以搭建4座桥将建筑物联系起来。城市2有两座建筑物,但不能搭建桥梁将它们连接。城市3只有一座建筑物,城市4有3座建筑物,可以搭建一座桥梁联系两栋建筑物,但不能与第三座建筑物联系在一起。
输入描述 Input Description
在输入的数据中的第一行包含描述城市的两个整数r 和c, 分别代表从北到南、从东到西的城市大小(1 <= r <= 50 and 1 <= c <= 50). 接下来的r 行, 每一行由c 个(“#”)和(“.”)组成的字符. 每一个字符表示一个单元格。“#”表示建筑物,“.”表示空地。
输出描述 Output Description
在输出的数据中有两行,第一行表示建筑物的数目。第二行输出桥的数目和所有桥的总长度。

一个联通块就是一座城市,两座城市搭桥即是联通块之间连边,注意的是联通块中有n个点,那就得连n条边QAQ
连边的时候方向是不变的,即搭的桥不能转弯,而且方向是可以偏移一行的……
对于联通块中的一个点,将其向正右(x,i),右上(x-1,i),右下(x+1,i),正左(x,i),左上(x-1,i),左下(x+1,i),正上(i,y),上左(i-1,y),上右(i+1,y),正下(i,y),下右(i+1,y),下左(i-1,y)单一方向寻找,如果路径上有另一联通块,就将其连边
所有的边全部建立之后进行最小生成树即可

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=233333;
int map[500][500];
bool use[500][500];
int x_x[9]={0,0,0,1,-1,1,1,-1,-1};
int y_y[9]={0,1,-1,0,0,1,-1,1,-1};
struct doubi{
    int x,y;
};
struct faq{
    int f,t,d;
}num[maxn];
int n,m;
queue<doubi> q;
void bfs(int i,int j,int cnt){
    memset(use,0,sizeof(use));
    doubi s;
    s.x=i,s.y=j;
    map[i][j]=cnt;
    q.push(s);
    while(!q.empty())
    {
        doubi u=q.front();
        q.pop();
        int x=u.x,y=u.y;
        for(int i=1;i<=8;i++){
            int X=x+x_x[i];
            int Y=y+y_y[i];
            if(X>=1&&X<=n&&Y>=1&&Y<=m&&!use[X][Y]&&map[X][Y]==-1){
                map[X][Y]=cnt;
                use[X][Y]=1;
                doubi nxt;
                nxt.x=X,nxt.y=Y;
                q.push(nxt);
            }
        }
    }
}
int fa[maxn];
bool cmp(faq a,faq b){
    return a.d<b.d;
}
int find(int a){
    if(fa[a]!=a) return fa[a]=find(fa[a]);
    else
    return a;
}
int main()
{
    scanf("%d%d",&n,&m);
    char x;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            cin>>x;
            if(x=='#'){
                map[i][j]=-1;
            }
        }
    }
    int cnt=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(map[i][j]==-1&&!use[i][j]){
                bfs(i,j,++cnt);
            }
        }
    }
    int tot=0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=m;j++){
            if(map[i][j]){
                for(int k=j;k<=m;k++){//横右 
                    if(map[i][k]&&map[i][k]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[i][k];
                        num[tot].d=abs(k-j-1);
                    }
                }
                for(int k=j;k<=m;k++){//横右上 
                    if(map[i+1][k]&&map[i+1][k]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[i+1][k];
                        num[tot].d=abs(k-j-1);
                    }
                }
                for(int k=j;k<=m;k++){//横右下 
                    if(map[i-1][k]&&map[i-1][k]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[i-1][k];
                        num[tot].d=abs(k-j-1);
                    }
                }
                for(int k=i;k<=n;k++){//竖下 
                    if(map[k][j]&&map[k][j]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[k][j];
                        num[tot].d=abs(k-i-1);
                    }
                }
                for(int k=i;k<=n;k++){//竖下右 
                    if(map[k][j+1]&&map[k][j+1]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[k][j+1];
                        num[tot].d=abs(k-i-1);
                    }
                }
                for(int k=i;k<=n;k++){//竖下左 
                    if(map[k][j-1]&&map[k][j-1]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[k][j-1];
                        num[tot].d=abs(k-i-1);
                    }
                }
                for(int k=j;k>=1;k--){//横左 
                    if(map[i][k]&&map[i][k]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[i][k];
                        num[tot].d=abs(k-j-1);
                    }
                }
                for(int k=j;k>=1;k--){//横左上 
                    if(map[i+1][k]&&map[i+1][k]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[i+1][k];
                        num[tot].d=abs(k-j-1);
                    }
                }
                for(int k=j;k>=1;k--){//横左下 
                    if(map[i-1][k]&&map[i-1][k]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[i-1][k];
                        num[tot].d=abs(k-j-1);
                    }
                }
                for(int k=i;k>=1;k--){//竖上 
                    if(map[k][j]&&map[k][j]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[k][j];
                        num[tot].d=abs(k-i-1);
                    }
                }
                for(int k=i;k>=1;k--){//竖上右 
                    if(map[k][j+1]&&map[k][j+1]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[k][j+1];
                        num[tot].d=abs(k-i-1);
                    }
                }
                for(int k=i;k>=1;k--){//竖上左 
                    if(map[k][j-1]&&map[k][j-1]!=map[i][j]){
                        num[++tot].f=map[i][j];
                        num[tot].t=map[k][j-1];
                        num[tot].d=abs(k-i-1);
                    }
                }
            }
        }
    }
    sort(num+1,num+1+tot,cmp);
    long long ans=0;
    int count=0;
    for(int i=1;i<=cnt;i++){
        fa[i]=i;
    }
    for(int i=1;i<=tot;i++){
        int x=find(num[i].f),y=find(num[i].t);
        if(x!=y){
            fa[x]=y;
            ans+=num[i].d;
            count++;
        }
    }
    cout<<cnt<<endl<<count<<" "<<ans<<endl;
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值