Description

有一个居住在多山岛屿的登山家,已经攀上了一座山峰,并且要攀爬另外一座更高的山峰。

更精确地说,岛上的每一点都有一个大于零的海拔(海面的海拔为零),并且如果登山家位于海拔Ei的山峰上,那么他的目标是到达其他海拔为Ej(Ej>Ei)的山峰。因为登山家在一个山峰上,所以无法马上向上爬——为了到达一个海拔更高的地点,登山家需要先下山才能上山。下山的路不及上山精彩,因此,登山家想将从当前地点到达更高山峰途中最低点的海拔最大化。

例如,如果岛屿的轮廓如图中所示,并且登山家在海拔为E4的山峰,那么有三个山峰有更高的海拔(E5,E6和E7),但是路途中最低点最高的路径是到达海拔E7的山峰的路径——在路上他不会走到海拔E2以下(在其他路径中他必须经过海拔E1的地点)。如果他从海拔E5的山峰出发,那么对应路径经过的最低海拔为E3(到达E6的路径),但是如果他从E6 出发,那么最低点就是E1。

岛屿的地图是一个二维的N*M的矩形网格,并且描述了岛屿每一部分的海拔——格子里的数字表示岛屿对应地区的海拔。如果两个各自有公共点,那么他们相邻。因此,每个格子(除了在边界上的)和其他8个格子相邻。一条路径是一系列的格子,序列中连续的两个格子相邻。一个“平区域”是一个相同海拔格子的集合,并且集合中任意两个格子能够用仅经过这个集合内格子的路径连接。任意两个等高的相邻格子属于同一“平区域” 。一座山峰,是一个相邻的格子中没有更高海拔的“平区域”。

写一个程序,找到所有山峰,并且计算每个山峰到达更高山峰路途中最大的最低海拔。对于岛上最高的山峰(岛上没有更高的山峰),可以确定登山家会离开岛屿寻找更高的山峰,因此,路途中的最低海拔为零(海平面的海拔)。

Input

输入的第一行包含两个整数N和M(1<=N,M<=2000,N*M<=10^5),分别是地图的高和宽。

接下来N行包含岛屿地图的描述。其中每行包含M个空格隔开的整数Eij(1<=Eij<=10^6)。格子Eij(对应地图的i 行j 列)的海拔为输入的i+1行第j 个整数。

Output

输出的第一行须包含一个整数P,岛屿中山峰的个数。接下来P行须每行包含两个整数:这座山峰的海拔及到达更高山峰途中最低点海拔的最大值。这些山峰的信息按照海拔降序输出;如果若干座山峰海拔相同,那么它们按照那个最低点的海拔降序输出。

Sample Input

输入1:

6 6

21 16 9 11 6 7

21 21 10 14 15 9

18 20 8 9 13 14

11 10 9 9 8 13

8 12 12 14 13 8

7 13 12 9 5 1

输入2:

5 3

16 14 16

14 14 15

12 17 16

12 13 10

16 11 16

Sample Output

输出1:

4

21 0

15 11

14 13

13 12

输出2:

5

17 0

16 15

16 14

16 13

16 13

Data Constraint

• 15 分的数据中N<=2或M<=2。

• 50 分的数据中有P<=500。

• 80 分的数据中有P<=5000。

题解

先将通高平区域进行合并
将所有的平区域按照从高到低排个序,依次按高到低的顺序加进图中,如果邻近的平区域都没被加入进图中,那么这个平区域一定是山峰。否则这个平区域属于比自己高的邻近的山峰。
如果一个平区域同时被属于多个山峰,那么除了最高的峰外,其他的峰都找到了一条到达更高的峰的路径,且这个平区域就是路径上高度最高的最低值(比这个最低值更低的还没有被加进图中呢)。这个时候,将小的峰往大的峰合并。
其他的峰他们的答案一定相同,所以可以用启发式合并。

代码

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int z[8][2]={{-1,-1},{-1,0},{-1,1},{0,-1},{0,1},{1,-1},{1,0},{1,1}};
int fx,fy,l,n,m,t,s,num,h,x,y,xx,yy,tot,sf,v[2003][2003],visit[2003][2003],g[100003],ans[100003][2],k[100003],fa[100003],p[100003],d[2003][2003],fb[100003],go[100003*2],head[100003],next[100003*2],nx[100003*2],ny[100003*2];
bool bz[100003],b[100003];
bool cmp(int x,int y){return k[x]>k[y];}
void insert(int a,int b,int x,int y)
{go[++tot]=b;next[tot]=head[a];head[a]=tot;nx[tot]=x;ny[tot]=y;
}
int getfather(int x){if (fa[x]==x) return x; else {fa[x]=getfather(fa[x]); return fa[x];}}
void kz(int x,int y)
{visit[x][y]=num;insert(num,d[x][y],x,y);for (int i=0;i<=7;i++){int xx=x+z[i][0],yy=y+z[i][1];if (xx>=1&&x<=n&&y>=1&&y<=m&&!visit[xx][yy]) if (v[x][y]==v[xx][yy]) kz(xx,yy);}
}
void qsort(int l,int r)
{if (l>=r) return;int i=l,j=r,midx=ans[(i+j)/2][0],midy=ans[(i+j)/2][1];while (i<j){while (ans[i][0]>midx||(ans[i][0]==midx&&ans[i][1]>midy)) i++;while (ans[j][0]<midx||(ans[j][0]==midx&&ans[j][1]<midy)) j--;if (i<=j){swap(ans[i],ans[j]);i++; j--;}}qsort(l,j);qsort(i,r);}
int main()
{//freopen("peaks.in","r",stdin);//freopen("peaks.out","w",stdout);scanf("%d%d",&n,&m);for (int i=1;i<=n;i++)for (int j=1;j<=m;j++){num++;scanf("%d",&v[i][j]);d[i][j]=num;}num=0;for (int i=1;i<=n;i++)for (int j=1;j<=m;j++)if (!visit[i][j]){num++;kz(i,j);k[num]=v[i][j];}for (int i=1;i<=num;i++) p[i]=i;for (int i=1;i<=n;i++)for (int j=1;j<=m;j++)for (int o=0;o<=7;o++){x=i+z[o][0]; y=j+z[o][1];if (v[x][y]>v[i][j]) bz[visit[i][j]]=1;}for (int i=1;i<=num;i++) if (!bz[i]) fb[i]=1;sort(p+1,p+num+1,cmp);for (int i=1;i<=num;i++) fa[i]=i;   for(int i=1;i<=num;i++){h=p[i];b[h]=1;for (int j=head[h];j;j=next[j]){x=nx[j];y=ny[j];for (int o=0;o<=7;o++){xx=x+z[o][0]; yy=y+z[o][1];if (visit[xx][yy]!=h&&b[visit[xx][yy]]){fx=getfather(visit[xx][yy]);fy=getfather(h);if (fx!=fy)if (k[fx]==k[fy]){fa[fy]=fx;fb[fx]+=fb[fy];}else if (k[fx]>k[fy]){fa[fy]=fx;for (int q=1;q<=fb[fy];q++){sf++;ans[sf][0]=k[fy];ans[sf][1]=k[h];}}else if (k[fx]<k[fy]){fa[fx]=fy;for (int q=1;q<=fb[fx];q++){sf++;ans[sf][0]=k[fx];ans[sf][1]=k[h];}}}}}}fx=getfather(num);for (int i=1;i<=fb[fx];i++) ans[++sf][0]=k[fx];printf("%d\n",sf);qsort(1,sf);for (int i=1;i<=sf;i++) printf("%d %d\n",ans[i][0],ans[i][1]);return 0;
}

转载于:https://www.cnblogs.com/Comfortable/p/8412231.html

[并查集][排序][dfs][启发式合并] JZOJ P3635 Peaks相关推荐

  1. PAT甲级1021 Deepest Root :[C++题解]树的最大深度、并查集、dfs求树的深度

    文章目录 题目分析 题目链接 题目分析 分析: 考察知识点:并查集.dfs.树的深度 给定n个结点,n-1条边,只要能保证只有1个连通分量,就是一棵树.否则的话就不是树,它是不连通的. 用并查集来看是 ...

  2. [并查集][排序] Jzoj P4223 旅游

    Description Input Output Sample Input 15 5 32 3 63341 5 157243 5 57054 3 123821 3 217266000100001300 ...

  3. LeetCode 1258. 近义词句子(哈希+并查集+排序+回溯)

    文章目录 1. 题目 2. 解题 1. 题目 给你一个近义词表 synonyms 和一个句子 text , synonyms 表中是一些近义词对 ,你可以将句子 text 中每个单词用它的近义词来替换 ...

  4. Gym - 101194G Pandaria (并查集+倍增+线段树合并)

    题意: 给定一个无向图.每个点有一种颜色.现在给定q个询问,每次询问x和w,求所有能通过边权值不超过w的边走到x的点的集合中,哪一种颜色的点出现的次数最多.次数相同时输出编号最小的那个颜色.强制在线. ...

  5. Codeforces Round #836 (Div. 2) E.Tick, Tock(在线:带权并查集/离线:dfs判环)

    题目 n*m(1<=n,m<=2e5,n*m<=2e5)的网格图, 有一些格子内已经放入了闹钟,当前时刻在[0,h)(1<=h<=1e9)之间 还有一些位置没有放闹钟,输 ...

  6. 连通图的判断(并查集, DFS, BFS)

    首先要明确什么是连通图??? 连通图:对于一个图来说,图中的任意一个点都能访问到所有的点,则说明该图连通 很明显,如果要判断一个图是否连通,则必须要从任意一个搜索一遍,判断是否到达了所有的点,则很快会 ...

  7. 【CodeForces - 616C 】The Labyrinth点石成金(并查集,dfs)

    题干: 小O无意间发现了一张藏宝图,它跟随藏宝图的指引来到了一个宫殿,宫殿的地板被分成了n*m块格子,每个格子上放置了金子或者石头 藏宝图告诉小O,它可以选择一块石头变成金子,并且带走与变化后的金子联 ...

  8. 单链表式并查集应用(解决区间合并,区间删除,染色问题)

    单链表式并查集应用 普通并查集(树状): p[i]p[i]p[i] 表示节点 iii 的父节点, iii 所在树的根节点是代表元素. 单链表式并查集(单链表状)时间复杂度 O(m元素值域+n)O(m_ ...

  9. CSP认证201512-4 送货[C++题解]:无向图欧拉路径、并查集、dfs

    题目分析 来源:acwing 分析: 无向图判断是否有欧拉路径:连通:度数为奇数的点,要么有2个,要么有0个. 如果有解,直接dfs求欧拉路径即可:只要有相连的边,就dfs遍历.当然,这里需要输出字典 ...

最新文章

  1. 如何看待导师直接说你写的论文就是垃圾?
  2. [教程]JS从糊涂到明白:一步一步编写计算器2 – 简化代码
  3. yar java_Yar 的传输协议学习以及 Java 版本的实现
  4. iview tooltip自动消失_惠州广日自动人行道价格大概多少
  5. python一行行写文件_python一行行写文件-女性时尚流行美容健康娱乐mv-ida网
  6. 高等数学与python高级应用_python高级应用程序与设计
  7. java调用ole ie_SWT中通过Automatioin的方式访问IE(升级版)
  8. 《深入理解JavaScript闭包和原型》笔记
  9. 防止ARP欺骗的方法
  10. 机原自检——第7章 机械的运转及其速度波动的调节
  11. 使用AJAX中的get请求中文乱码的问题
  12. 数据结构之二叉平衡树
  13. linux内核态访问串口,linux内核中串口驱动注册过程(tty驱动)[转]
  14. 不要迷信微服务,微服务就是个传说
  15. 用计算机开3次方,android系统计算器开3次方
  16. 云计算与大数据平台课堂作业
  17. twitter视频下载php,Twitter推特红心点赞H5动画按钮特效
  18. 网页视频播放插件ckplayer的使用-详细介绍
  19. IDEA如何设置热启动
  20. 幼儿园小朋友可以教创业者的事

热门文章

  1. mft按钮设计_哈汽机组660MW超临界空冷机组ETS设计及逻辑说明
  2. python多继承_python作用域和多继承
  3. 【Pytorch神经网络理论篇】 03 Pytorch快速上手(三)张量的数据操作
  4. c语言作业题五六章答案,数据结构(C语言版)第五六章习题答案
  5. LeetCode 2119. 反转两次的数字
  6. python 剪切一行内容到另一个文件
  7. LeetCode 919. 完全二叉树插入器(层序遍历队列)
  8. cms安装教程Linux,DoraCMS安装教程(linux)
  9. sklearn分类器性能评估
  10. html的实战性介绍