codevs 1002 搭桥

//终于A了这道让我难受的题你知道那少个对勾的感觉有多难受么强迫症没法忍啊啊啊

1002 搭桥
时间限制: 1 s
空间限制: 128000 KB
题目等级 : 黄金 Gold
题解
题目描述 Description
有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点相联系,则它们属于同一座建筑物。现在想在这些建筑物之间搭建一些桥梁,其中桥梁只能沿着矩形的方格的边沿搭建,如下图城市1有5栋建筑物,可以搭建4座桥将建筑物联系起来。城市2有两座建筑物,但不能搭建桥梁将它们连接。城市3只有一座建筑物,城市4有3座建筑物,可以搭建一座桥梁联系两栋建筑物,但不能与第三座建筑物联系在一起。

输入描述 Input Description
在输入的数据中的第一行包含描述城市的两个整数r 和c, 分别代表从北到南、从东到西的城市大小(1 <= r <= 50 and 1 <= c <= 50). 接下来的r 行, 每一行由c 个(“#”)和(“.”)组成的字符. 每一个字符表示一个单元格。“#”表示建筑物,“.”表示空地。

输出描述 Output Description
在输出的数据中有两行,第一行表示建筑物的数目。第二行输出桥的数目和所有桥的总长度。

样例输入 Sample Input
样例1

3 5

..#..

样例2

3 5

…..

….#

样例3

3 5

.

.#.

.

样例4:

3 5

.#..

…..

….#

样例输出 Sample Output
样例1

5

4 4

样例2

2

0 0

样例3

1

0 0

样例4

3

1 1

一开始看这题目标签 最小生成树 ??一脸懵逼

这哪里是最小生成树了啊喂。。

后来吧 实在看它不顺眼 实在想A了它换个√看,,

于是乎 认真读题+开脑洞后 (不得不承认有些题真的需要开一开脑洞)

大概看懂了题的意思

现在我自己来描述一遍

一个平面上有若干个点 若干个点相连(八个方向相连)形成一座城市
这些城市之间仅能水平或竖直联通(道路不能拐弯) 求城市个数及能够将各个城市连起来的道路最小总长度 ;

那么现在很显然 第一个问题dfs或bfs处理每个点就可以了

第二个问题 最小生成树当然kruskal最简单 问题是怎么求出各个城市间的道路和道路长度 因为仅能水平或竖直连通两个城市 所以直接分别纵向和横向枚举,记录当前到达的点有没有城市,如果有城市那么是不是非记录的城市 如果是那么存下当前记录城市到该点城市的距离,当前已走过的距离刷新为0,更新当前城市为该点城市;

然而这样只有60分

因为并没有考虑全面

给定的平面图是一个矩形方阵 因此上下两行(或者左右两列)城市之间也可以有道路连接 因此每次判断要加上某点下一行(或下一列)的点;

现在是80分了

为啥还不对咯。。
考虑这样的一种情况:
|1■| □| □|
| □| □|2■|
| □|3■| □|

按照上面的思路(枚举记录)来说 1到2的距离是可以算出来并记录下来的 然而3到2也应该是能连接的 但是实际上并没有算出3到2的距离;

如果会出现这种情况 那么3一定是在2的下一行并且列数在2的前面
所以直接把原来的正向枚举反过来再枚举一遍不就好了??

所以 我复制后并稍微改了一下一开始的枚举点的代码,~(更暴力了一些。。) ~

100。

(我感觉你不会想看代码的。。)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
#include<cstdlib>
#include<cmath>
#include<set>
using namespace std;
int n,m,tu[60][60],visit[60][60],map[60][60],p,pp,sum,longer,fa[3000];
int zx[9]={0,1,1,1,0,0,-1,-1,-1},
    zy[9]={0,0,1,-1,-1,1,-1,0,1};
struct rec{
    int from,to,w;
}e[500001];
void dfs(int x,int y)
{
    map[x][y]=p;
    visit[x][y]=1;
    for(int i=1;i<=8;i++)
    {
        int tx=zx[i]+x,ty=zy[i]+y;
        if(!visit[tx][ty]&&tu[tx][ty])
        {
            dfs(tx,ty);
        }
    }
}
bool cmp(rec a,rec b)
{
    return a.w<b.w;
}
int find(int a){
    if(fa[a]==a)return a;
    return fa[a]=find(fa[a]);
}
void kruskal()
{
    for(int i=1;i<=p;i++)
    {
        fa[i]=i;
    }
    sort(e+1,e+pp+1,cmp);
    for(int i=1;i<=pp;i++)
    {
        if(find(e[i].to)!=find(e[i].from))
        {
            fa[find(e[i].to)]=find(e[i].from);
            //find(e[i].to);
            sum++;
            longer+=e[i].w;
        }
    }
}
void makedis()
{
    int dis=0,now=0;
    for(int i=1;i<n;i++)
    {
        now=0,dis=0;
        for(int j=1;j<=m;j++)
        {
            if(map[i][j])
            {
                if(now==0)
                {
                    now=map[i][j];
                    dis=0;
                }
                else {
                    if(map[i][j]&&map[i][j]!=now)
                    {
                        pp++;
                        e[pp].from=now;
                        e[pp].to=map[i][j];
                        e[pp].w=dis;
                        dis=0;
                        now=map[i][j];
                    }

                }
            }
            else if(map[i+1][j])
            {
                if(now==0)
                {
                    now=map[i+1][j];
                    dis=0;
                }
                else {
                    if(map[i+1][j]&&map[i+1][j]!=now)
                    {
                        pp++;
                        e[pp].from=now;
                        e[pp].to=map[i+1][j];
                        e[pp].w=dis;
                        dis=0;
                        now=map[i+1][j];
                    }

                }
            }
            else dis++; 
        }
    }
    for(int i=1;i<n;i++)
    {
        now=0,dis=0;
        for(int j=m;j>=1;j--)
        {
            if(map[i][j])
            {
                if(now==0)
                {
                    now=map[i][j];
                    dis=0;
                }
                else {
                    if(map[i][j]&&map[i][j]!=now)
                    {
                        pp++;
                        e[pp].from=now;
                        e[pp].to=map[i][j];
                        e[pp].w=dis;
                        dis=0;
                        now=map[i][j];
                    }

                }
            }
            else if(map[i+1][j])
            {
                if(now==0)
                {
                    now=map[i+1][j];
                    dis=0;
                }
                else {
                    if(map[i+1][j]&&map[i+1][j]!=now)
                    {
                        pp++;
                        e[pp].from=now;
                        e[pp].to=map[i+1][j];
                        e[pp].w=dis;
                        dis=0;
                        now=map[i+1][j];
                    }

                }
            }
            else dis++; 
        }
    }
    for(int j=1;j<m;j++)
    {
        dis=0,now=0;
        for(int i=n;i>=n;i--)
        {
            if(map[i][j])
            {
                if(now==0)
                {
                    now=map[i][j];
                    dis=0;
                }
                else {
                    if(map[i][j]!=now)
                    {
                        pp++;
                        e[pp].from=now;
                        e[pp].to=map[i][j];
                        e[pp].w=dis;
                        dis=0;
                        now=map[i][j];
                    }
                }
            }
            else if(map[i][j+1])
            {
                if(now==0)
                {
                    now=map[i][j+1];
                    dis=0;
                }
                else {
                    if(map[i][j+1]!=now)
                    {
                        pp++;
                        e[pp].from=now;
                        e[pp].to=map[i][j+1];
                        e[pp].w=dis;
                        dis=0;
                        now=map[i][j+1];
                    }
                }
            }
            else dis++;
        }
    }
    for(int j=1;j<m;j++)
    {
        dis=0,now=0;
        for(int i=1;i<=n;i++)
        {
            if(map[i][j])
            {
                if(now==0)
                {
                    now=map[i][j];
                    dis=0;
                }
                else {
                    if(map[i][j]!=now)
                    {
                        pp++;
                        e[pp].from=now;
                        e[pp].to=map[i][j];
                        e[pp].w=dis;
                        dis=0;
                        now=map[i][j];
                    }
                }
            }
            else if(map[i][j+1])
            {
                if(now==0)
                {
                    now=map[i][j+1];
                    dis=0;
                }
                else {
                    if(map[i][j+1]!=now)
                    {
                        pp++;
                        e[pp].from=now;
                        e[pp].to=map[i][j+1];
                        e[pp].w=dis;
                        dis=0;
                        now=map[i][j+1];
                    }
                }
            }
            else dis++;
        }
    }
}
int main()
{
    //ios::sync_with_stdio(false);
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            char c;
            cin>>c;
            if(c=='#')tu[i][j]=1;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(!visit[i][j]&&tu[i][j])
            {
                p++;
                dfs(i,j);
            }
        }
    }
    cout<<p<<"\n";

    makedis();

    kruskal();

    cout<<sum<<" "<<longer;

    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值