1002 搭桥

 时间限制: 1 s
 空间限制: 128000 KB
 题目等级 : 黄金 Gold
题目描述 Description

有一矩形区域的城市中建筑了若干建筑物,如果某两个单元格有一个点相联系,则它们属于同一座建筑物。现在想在这些建筑物之间搭建一些桥梁,其中桥梁只能沿着矩形的方格的边沿搭建,如下图城市1有5栋建筑物,可以搭建4座桥将建筑物联系起来。城市2有两座建筑物,但不能搭建桥梁将它们连接。城市3只有一座建筑物,城市4有3座建筑物,可以搭建一座桥梁联系两栋建筑物,但不能与第三座建筑物联系在一起。

输入描述 Input Description

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

输出描述 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

数据范围及提示 Data Size & Hint

见描述


这题我真心没觉得有多模板题,一些细节也很坑,至少我是嗑了很久,说是模板题的大爷们我先献上膝盖:)。

这道题挺神奇的,比如我这种辣鸡第一眼就没看出是最小生成树,最后乱搞碰壁才发现可以写prim…

坑点挺多的,而且题目本身也很迷。

思路:无向图。第一问就是求联通块个数,可以用搜索水过,但是要注意“如果某两个单元格有一个点相联系,则它们属于同一座建筑物”,意思就是要搜索每个单元格的八个方向。后两问是建立在第一问上的。把相邻的建筑合成一个建筑来提高效率。我这里使用了并查集。在第一问的搜索中加入把相邻的建筑父亲都指向编号,比如第一组相邻的建筑合成的一个建筑编号为1,第二组编号为2…这就是把这些建筑缩为点,点的编号就是建筑组的编号。接下来考虑如何建边。建边也是这道题目的难点之一。我们可以发现对于每一个建筑,如果它上面那一行或者下面那一行有建筑的话,它们之间桥梁的距离就可以用横坐标相减再减1计算出来,而对于同一行的也是如此。对于每一列的也可以这样枚举。这里我用的是邻接矩阵存储图,注意存两个点之间的距离时要用min,因为你不知道这条边会不会比它已经存好的边短。建完图后我们就来跑Prim。有很多建筑组,而且这些建筑组之间不一定有边联通。以每个dis值还没确定的点为源点跑Prim,最后计算答案就可以了。

 #include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int inf=;
long long ans2,ans3;
int n,m,f[],num[][],e[][],ans1,dis[];
int D[][]={{,},{,},{,-},{-,},{-,-},{,},{,-},{-,}};
bool map[][],map2[][],book[];
int read()
{
int x=,f=; char c=getchar();
while (c<'' || c>'') {if (c=='-') f=-; c=getchar();}
while (c>=''&& c<='') {x=x*+c-''; c=getchar();}
return (x*f);
}
int getf(int x)
{
if (f[x]==x) return x;
f[x]=getf(f[x]);
return f[x];
}
bool Merge(int a,int b)
{
a=getf(a); b=getf(b);
if (a!=b) {
return ;
}
return ;
}
void dfs(int x,int y)
{
num[x][y]=ans1;
map2[x][y]=;
for (int i=; i<=; i++) {
int xx=x+D[i][],yy=y+D[i][];
if (xx>=&&xx<=n&&yy>=&&yy<=m&&map2[xx][yy]==) {
f[num[xx][yy]]=f[num[x][y]];
dfs(xx,yy);
}
}
return;
}
int main()
{
char c;
n=read(); m=read();
for (int i=; i<=n; i++)
for (int j=; j<=m; j++) {
cin>>c;
if (c=='#') {
map[i][j]=;
map2[i][j]=;
}
}
for (int i=; i<=n; i++)
for (int j=; j<=m; j++)
if (map2[i][j]==) {
ans1++;
f[ans1]=ans1;
dfs(i,j);
}
if (ans1==) {
cout<<<<endl<<<<" "<<<<endl;
return ;
}
for (int i=; i<=ans1; i++)
for (int j=; j<=ans1; j++)
e[i][j]=inf;
for (int i=; i<=n; i++) {
for (int j=; j<=m; j++) {
if (map[i][j]==) {
if (i!=) {
for (int k=; k<=m; k++)
if (map[i-][k]== && Merge(num[i-][k],num[i][j])) {
e[num[i-][k]][num[i][j]]=min(e[num[i-][k]][num[i][j]],abs(k-j)-);
e[num[i][j]][num[i-][k]]=e[num[i-][k]][num[i][j]];
}
}
if (i!=n) {
for (int k=; k<=m; k++)
if (map[i+][k]== && Merge(num[i+][k],num[i][j])) {
e[num[i+][k]][num[i][j]]=min(abs(k-j)-,e[num[i+][k]][num[i][j]]);
e[num[i][j]][num[i+][k]]=e[num[i+][k]][num[i][j]];
}
}
for (int k=; k<=m; k++)
if (map[i][k]== && Merge(num[i][k],num[i][j])) {
e[num[i][k]][num[i][j]]=min(abs(k-j)-,e[num[i][k]][num[i][j]]);
e[num[i][j]][num[i][k]]=e[num[i][k]][num[i][j]];
}
if (j!=) {
for (int k=; k<=n; k++)
if (map[k][j-]== && Merge(num[k][j-],num[i][j])) {
e[num[k][j-]][num[i][j]]=min(abs(k-i)-,e[num[k][j-]][num[i][j]]);
e[num[i][j]][num[k][j-]]=e[num[k][j-]][num[i][j]];
}
}
if (j!=m) {
for (int k=; k<=n; k++)
if (map[k][j+]== && Merge(num[k][j+],num[i][j])) {
e[num[k][j+]][num[i][j]]=min(abs(k-i)-,e[num[k][j+]][num[i][j]]);
e[num[i][j]][num[k][j+]]=e[num[k][j+]][num[i][j]];
}
}
for (int k=; k<=n; k++){
if (map[k][j]== && Merge(num[k][j],num[i][j])) { e[num[k][j]][num[i][j]]=min(abs(k-i)-,e[num[k][j]][num[i][j]]);
e[num[i][j]][num[k][j]]=e[num[k][j]][num[i][j]];
}
}
}
}
}
for (int i=; i<=ans1; i++) {
if (book[i]==) {
for (int j=; j<=ans1; j++) dis[j]=inf;
dis[i]=;
for (int k=; k<ans1; k++) {
int MIN=inf,u;
for (int j=; j<=ans1; j++)
if (book[j]==&&dis[j]<MIN) {
MIN=dis[j];
u=j;
}
if (MIN==inf) break;
book[u]=;
for (int j=; j<=ans1; j++)
if (book[j]==&&e[u][j]<dis[j]) dis[j]=e[u][j];
}
for (int j=; j<=ans1; j++)
if (dis[j]!=inf && dis[j]!=) {
ans2++;
ans3+=dis[j];
}
}
}
printf("%d\n%lld %lld\n",ans1,ans2,ans3);
return ;
}

搭桥

有问题可以直接在评论里面提问,有需要转载的请得到我的允许,否则按侵权处理。


Elena loves NiroBC forever!

搭桥|codevs1002|最小生成树|Prim|并查集|Elena的更多相关文章

  1. 线段树、最短路径、最小生成树、并查集、二分图匹配、最近公共祖先--C++模板

    线段树(区间修改,区间和): #include <cstdio> #include <iostream> #include <cstring> using name ...

  2. hdu5441(2015长春赛区网络赛1005)类最小生成树、并查集

    题意:有一张无向图,一些点之间有有权边,某条路径的值等于路径上所有边的边权的最大值,而某个点对的值为这两点间所有路径的值的最小值,给出多个询问,每个询问有一个值,询问有多少点对满足其值小于等于询问值. ...

  3. 2018.11.02 NOIP模拟 飞越行星带(最小生成树/二分+并查集)

    传送门 发现题目要求的就是从下到上的瓶颈路. 画个图出来发现跟去年noipnoipnoip提高组的奶酪差不多. 于是可以二分宽度+并查集检验,或者直接求瓶颈. 代码

  4. URAL-1982-Electrification Plan最小生成树或并查集

    Electrification Plan 题意:在一个无向图中,给你几个源点,找出把所有点连接到源点后最小的消费: 可以利用并查集: 先用结构体把每个边存起来,再按照消费大小排序.之后从消费小的到大的 ...

  5. hdu 1301 Jungle Roads krusckal,最小生成树,并查集

    The Head Elder of the tropical island of Lagrishan has a problem. A burst of foreign aid money was s ...

  6. 最小生成树,并查集的思想 nyoj1239

    #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; int ...

  7. 【BZOJ4144】[AMPPZ2014]Petrol(最短路+最小生成树+并查集)

    Description 给定一个n个点.m条边的带权无向图,其中有s个点是加油站. 每辆车都有一个油量上限b,即每次行走距离不能超过b,但在加油站可以补满. q次询问,每次给出x,y,b,表示出发点是 ...

  8. HDU-1272小希的迷宫,并查集?其实不用并查集;

    小希的迷宫                                                                                               ...

  9. 稀疏图(邻接链表),并查集,最短路径(Dijkstra,spfa),最小生成树(kruskal,prim)

    全部函数通过杭电 1142,1162,1198,1213等题目测试. #include<iostream> #include<vector> #include<queue ...

随机推荐

  1. PL/SQL学习笔记之变量、常量、字面量、字符串

    一:变量 1:变量声明与初始化 variable_name datatype(约束) [:= | DEFAULT 初始值] 如: sales , ); name ); a ; greetings ) ...

  2. springboot 项目中获取默认注入的序列化对象 ObjectMapper

    在 springboot 项目中使用 @SpringBootApplication 会自动标记 @EnableAutoConfiguration 在接口中经常需要使用时间类型,Date ,如果想要格式 ...

  3. ECMAScript 6 入门之字符串

    1.新增字符串的方法 1.字符是否存在 console.log("Yo".indexOf("Y")!=-1); console.log("Yo&quo ...

  4. C#中的Action<>和Func<>

    其实他们两个都是委托[代理]的简写形式. 一.[action<>]指定那些只有输入参数,没有返回值的委托 Delegate的代码: public delegate void myDeleg ...

  5. Clustered Shading架构实现步骤

    最终决定越过Forward+,一步到位,直接调整至更先进的Clustered架构.步骤如下: 里程碑1:以CPU方式实现Light Culling,旨在理念验证,并与D3D10兼容里程碑2:以GPU ...

  6. linux每日命令(31):tar命令

    tar命令可以为linux的文件和目录创建档案.利用tar,可以为某一特定文件创建档案(备份文件),也可以在档案中改变文件,或者向档案中加入新的文件.tar最初被用来在磁带上创建档案,现在,用户可以在 ...

  7. Adam算法

    结合了Momentum 和RMSprop算法的优点

  8. 创建shell脚本

    1.写一个脚本 a) 用touch命令创建一个文件:touch my_script b) 用vim编辑器打开my_script文件:vi my_script c) 用vim编辑器编辑my_script ...

  9. Ubuntu和centos离线安装软件包(apt和yum)

    linux安装软件包要解决包依赖问题,不能简单安装包本身. 离线安装基本思想都是先在一台设备上安装下载所有依赖包,然后拷贝所有依赖包到新设备上安装. Ubuntu下apt离线安装包 执行apt upd ...

  10. WebRTC 零基础开发者教程(中文版)下载

    WebRTC 简介 WebRTC,是一个支持网页浏览器进行实时语音通话或视频聊天的技术,是谷歌2010年以6820万美元收购Global IP Solutions公司而获得的一项技术. WebRTC提 ...