[codevs1002]搭桥

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

试题分析:这个题我一开始看分类是搜索,并没有想到并查集……后来看了眼黄学长的博客,恍然大悟TAT

标程就是DFS+并查集

①用dfs联通块求第一问,然后把块标号

②枚举块的延伸,建立桥,排序路径长度(如图)

显然,在一个方格的一点,如果他向上延伸但是上面有块与他一个联通块,那么他就可以舍去

③merge并统计答案

代码

#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<stack>
#include<vector>
#include<algorithm>
//#include<cmath> using namespace std;
const int INF = 9999999;
#define LL long long inline int read(){
int x=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) x=x*10+c-'0';
return x*f;
}
int N,M;
int Map[101][101];
char c;
int cnt;
int vis[52][52]; int dfsans1(int a,int b){
vis[a][b]=cnt+1;
if(Map[a-1][b]&&!vis[a-1][b]) dfsans1(a-1,b);
if(Map[a+1][b]&&!vis[a+1][b]) dfsans1(a+1,b);
if(Map[a][b-1]&&!vis[a][b-1]) dfsans1(a,b-1);
if(Map[a][b+1]&&!vis[a][b+1]) dfsans1(a,b+1);
if(Map[a-1][b+1]&&!vis[a-1][b+1]) dfsans1(a-1,b+1);
if(Map[a+1][b-1]&&!vis[a+1][b-1]) dfsans1(a+1,b-1);
if(Map[a+1][b+1]&&!vis[a+1][b+1]) dfsans1(a+1,b+1);
if(Map[a-1][b-1]&&!vis[a-1][b-1]) dfsans1(a-1,b-1);
}
int temp;
struct data{
int f,s,ds;
}a[100001];
int fa[1001]; bool cmp(data a,data b){
return a.ds<b.ds;
} int ins(int x,int y,int x1,int y1,int dis){
if(!Map[x1][y1]) return 1;
if(vis[x][y]==vis[x1][y1]) return 0;
temp++;
a[temp].f=vis[x][y];
a[temp].s=vis[x1][y1];
a[temp].ds=dis-1;
return 1;
} void init(){
for(int i=1;i<=cnt;i++) fa[i]=i;
}
int find(int x){return x==fa[x]?x:fa[x]=find(fa[x]);}
void GA(){
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
if(Map[i][j]){
for(int k=i+1;k<=N;k++)
if(!ins(i,j,k,j,k-i)||!ins(i,j,k,j+1,k-i)||!ins(i,j,k,j-1,k-i)) break;
for(int k=i-1;k>=1;k--)
if(!ins(i,j,k,j,i-k)||!ins(i,j,k,j+1,i-k)||!ins(i,j,k,j-1,i-k)) break;
for(int l=j+1;l<=M;l++)
if(!ins(i,j,i,l,l-j)||!ins(i,j,i+1,l,l-j)||!ins(i,j,i-1,l,l-j)) break;
for(int l=j-1;l>=1;l--)
if(!ins(i,j,i,l,j-l)||!ins(i,j,i+1,l,j-l)||!ins(i,j,i-1,l,j-l)) break;
}
}
}
sort(a+1,a+1+temp,cmp);
int ans=0,tmp=0;
init();
for(int i=1;i<=temp;i++){
int xx=find(a[i].f),yy=find(a[i].s);
if(xx!=yy){tmp++;fa[yy]=xx;ans+=a[i].ds;}
}
printf("%d %d\n",tmp,ans);
} int main(){
N=read(),M=read();
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
cin>>c;
if(c=='#')Map[i][j]=1;
}
}
for(int i=1;i<=N;i++){
for(int j=1;j<=M;j++){
if(!vis[i][j]&&Map[i][j]) dfsans1(i,j),cnt++;
}
}
printf("%d\n",cnt);
if(cnt==0){
printf("0 0\n");
return 0;
}
GA();
return 0;
}

【并查集】【DFS】搭桥的更多相关文章

  1. HDU 1232 并查集/dfs

    原题: http://acm.hdu.edu.cn/showproblem.php?pid=1232 我的第一道并查集题目,刚刚学会,我是照着<啊哈算法>这本书学会的,感觉非常通俗易懂,另 ...

  2. 1021.Deepest Root (并查集+DFS树的深度)

    A graph which is connected and acyclic can be considered a tree. The height of the tree depends on t ...

  3. POJ1291-并查集/dfs

    并查集 题意:找出给定的这些话中是否有冲突.若没有则最多有多少句是对的. /* 思路:如果第x句说y是对的,则x,y必定是一起的,x+n,y+n是一起的:反之x,y+n//y,x+n是一起的. 利用并 ...

  4. F2 - Spanning Tree with One Fixed Degree - 并查集+DFS

    这道题还是非常有意思的,题意很简单,就是给定一个图,和图上的双向边,要求1号节点的度(连接边的条数)等于K,求这棵树的生成树. 我们首先要解决,如何让1号节点的度时为k的呢???而且求的是生成树,意思 ...

  5. UVA208-Firetruck(并查集+dfs)

    Problem UVA208-Firetruck Accept:1733  Submit:14538 Time Limit: 3000 mSec  Problem Description The Ce ...

  6. 2018 计蒜之道复赛 贝壳找房魔法师顾问(并查集+dfs判环)

    贝壳找房在遥远的传奇境外,找到了一个强大的魔法师顾问.他有 22 串数量相同的法力水晶,每个法力水晶可能有不同的颜色.为了方便起见,可以将每串法力水晶视为一个长度不大于 10^5105,字符集不大于  ...

  7. Codeforces 455C Civilization(并查集+dfs)

    题目链接:Codeforces 455C Civilization 题目大意:给定N.M和Q,N表示有N个城市,M条已经修好的路,修好的路是不能改变的.然后是Q次操作.操作分为两种.一种是查询城市x所 ...

  8. hdu6370 并查集+dfs

    Werewolf Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total ...

  9. POJ 3728 The merchant(并查集+DFS)

    [题目链接] http://poj.org/problem?id=3728 [题目大意] 给出一棵树,每个点上都可以交易货物,现在给出某货物在不同点的价格, 问从u到v的路程中,只允许做一次买入和一次 ...

  10. 牛客练习赛16 C 任意点【并查集/DFS/建图模型】

    链接:https://www.nowcoder.com/acm/contest/84/C 来源:牛客网 题目描述 平面上有若干个点,从每个点出发,你可以往东南西北任意方向走,直到碰到另一个点,然后才可 ...

随机推荐

  1. Shuffle Cards(牛客第三场+splay)

    题目: 题意:将1~n的数进行m次操作,每次操作将第pi位到pi+si-1位的数字移到第一位,求最后的排列. 思路:现在还没不会写splay,在知道这是splay模板题后找了一波别人的模板,虽然过了, ...

  2. 结合promise对原生fetch的两个then用法理解

    前言:该问题是由于看到fetch的then方法的使用,产生的疑问,在深入了解并记录对promise的个人理解 首先看一下fetch请求使用案例: 案例效果:点击页面按钮,请求当前目录下的arr.txt ...

  3. bootstrap 弹窗 数据清除

    bootstrap modal操作简单易用, //清除弹窗原数据 $("#create_modal").on("hidden.bs.modal", functi ...

  4. xctf一道反序列化题

    题目地址:http://120.24.86.145:8006/test1/ 右键get源码: <?php $user = $_GET["txt"]; $file = $_GE ...

  5. Python标准库笔记(4) — collections模块

    这个模块提供几个非常有用的Python容器类型 1.容器 名称 功能描述 OrderedDict 保持了key插入顺序的dict namedtuple 生成可以使用名字来访问元素内容的tuple子类 ...

  6. python实战===一句python代码搭建FTP服务

    环境搭建: python windows/linux pip install pyftpdlib  (安装失败请到这里下载:https://pypi.python.org/pypi/pyftpdlib ...

  7. 2017多校第6场 HDU 6097 Mindis 计算几何,圆的反演

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6097 题意:有一个圆心在原点的圆,给定圆的半径,给定P.Q两点坐标(PO=QO,P.Q不在圆外),取圆 ...

  8. yml格式

    是什么? yml文件扩展名是YAML的缩写,YAML于2001年出现,是一种数据描述语言,和xml类似 为什么用它? 我们在做javaweb项目的时候最常见的就是.xml配置文件和properitie ...

  9. C# 笔记——排序

    首先,一张图看懂8中排序之间的关系: 平均速度最快:快速排序 所需辅助空间最多:归并排序 所需辅助空间最少:堆排序 不稳定:快速排序,希尔排序,堆排序. 1. 直接插入排序 基本思想:在要排序的一组数 ...

  10. JVM 核心机制(类加载器、自定义文件系统类加载器、网络自定义类加载器