我写一篇绝对原创的题解,算法原创,求洛谷通过!!!(让更多人看到这篇题解)


绝大多数人肯定认为这道题是一道模拟题

以下为正解

我们来看一下这一道题,其实就是找到左右高点,在模拟。

但是这个是正常人的想法,现在我来将一个非正常人的做法。

算法的名字叫做最小生成树?!

注:虽然这个算法不叫歪解 滑稽

是不是非常的神奇???(我是看到没有人写这种题解才写的,如果有大佬在我之前就已经想到了,那么我也就只能%%%了)

我这里有一道关于这个题目的二维版,召唤传送门:传送 本人不喜欢懒开个人公开赛,所以这个题目也在洛谷的题库中没有上传。。。


好了!我们回到正题!

我们先讲一下算法步骤,在解释!

算法步骤

我们设置一个0号节点,作为我们最小生成树的虚拟根节点,这样我们就只需要找到关于0号节点的最小生成树。然后在0号节点和两端的1号节点和n号节点建一条长度为1和n的高度的边,这个时候我们只需要建立单向边就可以了,因为这个边只是供给我们计算最小生成树用的。

接着我们在从(2~n-1)这个之间,每两个块都直接建一条边,这个边长为两个块之间较高的高度。建完全部的边,那么我们就做一遍最小生成树,这个生成树的根节点是0。然后我们将这个最小生成树进行一次遍历,算出从根节点到每个节点的路径的上的某一条路的上的最大值,这个最大值作为dist[i],然后我们计算我们的答案就是dist[i]在减去原来的高度。

算法解释

其实我们就只是在模拟水流。根据牛顿万有引力定律,这个H2O呢?一定会向着地球靠近,算了也不讲了!也就是说我们需要找到一条路径这个水能从最高的地方流下来,因为水一定是往低的而且是在自己旁边的地方留出去,所以这就使得我们可以用最小生成树来做这一道题。

再说的简单一点,我们需要找到一条路使得我们的水流能只上升最短的高度就流出去。为什么?其实也和贪心有一点相似,因为如果你要积水一定是积到某个边缘部分,而且肯定不会再上升,所以我们需要在找到一条能跑到边缘的路,而且这个路的高度总和最小。

根据以上的特性,我么就可以想到一个算法,可以解出图上的所有点到某个点的总距离和最短,那么就是最小生成树了。

而如果有人要问这个0号节点的实际意义,其实也是有的,我觉得应该是包含边缘的全部的节点。

但是为什么我们最小生成树跑出来的答案并不是直接的答案?

because,我们建的边只是最大值,所以我们得到的这个答案就只是我们水流流进来可以跨越的合法最大高度,所以要积的水就是现在算出的的答案在减去我们原来的高度。

以下提供AC代码:

#include <bits/stdc++.h>
#define ms(a,b) memset(a,b,sizeof(a))
using namespace std;
const int Maxn=10005;
struct Edge{
int u,v,w;
bool operator <(const Edge a)const { //重载运算符,这样再排序的时候就不用写cmp了
return w<a.w;
}
}edge[Maxn];
struct Edge2{
int to,next,w;
}edge2[Maxn<<1];
int head[Maxn],fa[Maxn],h[Maxn],dist[Maxn];
int vis[Maxn],nedge,Nedge,n;
inline int read() {//快读
int w=0,x=0; char ch=0;
while (!isdigit(ch)) {w|=ch=='-';ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return w?-x:x;
}
inline int Min(int n,int m) {return n<m?n:m;}
inline int Max(int n,int m) {return n>m?n:m;};
inline void Add_Edge (int u,int v,int w) {edge[++Nedge] =(Edge ){u,v,w};}//第一次加边
inline void Add_Edge2(int u,int v,int w) {edge2[nedge]=(Edge2){v,head[u],w};head[u]=nedge++;}//第二次加边
inline int gf(int x) {return fa[x]==x?fa[x]:fa[x]=gf(fa[x]);}//并查集查找祖先+路径压缩
inline void dfs(int k,int maxlong) {//暴力查询
for (int i=head[k];i!=-1;i=edge2[i].next) {
if (vis[edge2[i].to]) vis[edge2[i].to]=0,dist[edge2[i].to]=max(maxlong,edge2[i].w),dfs(edge2[i].to,dist[edge2[i].to]);
}
}
int main() {
n=read();
for (int i=1;i<=n;i++) h[i]=read(),fa[i]=i; fa[0]=0;
Add_Edge(0,1,h[1]),Add_Edge(0,n,h[n]);//建虚拟边
for (int i=2;i<n;i++) Add_Edge(i,i-1,Max(h[i],h[i-1])),Add_Edge(i,i+1,Max(h[i],h[i+1]));//继续建边
sort(edge+1,edge+1+Nedge);//排序
ms(head,-1);//这个head数组
int cnt=0;
for (int i=1;i<=Nedge;i++) {
int ance1=gf(edge[i].u),ance2=gf(edge[i].v);
if (ance1!=ance2) {//最小生成树
fa[ance1]=ance2;//合并
cnt++;//节点个数+1
Add_Edge2(edge[i].u,edge[i].v,edge[i].w);
Add_Edge2(edge[i].v,edge[i].u,edge[i].w);//这里要建双向边。
}
if (cnt==n) break;//也为有一个虚拟点,所以我们要到n的时候在结束
}
for (int i=1;i<=n;i++) vis[i]=1; vis[0]=0; dfs(0,0);//暴力求解到根节点的路径上的最大值
int ans=0;
for (int i=1;i<=n;i++) ans+=dist[i]-h[i];//算出我们需要的答案
printf("%d\n",ans);
return 0;
}

【洛谷P1318积水面积】最小生成树的更多相关文章

  1. 洛谷 P1318 积水面积

    P1318 积水面积 题目描述 一组正整数,分别表示由正方体迭起的柱子的高度.若某高度值为x,表示由x个正立方的方块迭起(如下图,0<=x<=5000).找出所有可能积水的地方(图中蓝色部 ...

  2. 洛谷P1318 积水面积

    题目描述 一组正整数,分别表示由正方体叠起的柱子的高度.若某高度值为\(x\),表示由\(x\)个正立方的方块迭起(如下图,\(0<=x<=5000\)).找出所有可能积水的地方(图中蓝色 ...

  3. Luogu P1318 积水面积

    题目描述 一组正整数,分别表示由正方体迭起的柱子的高度.若某高度值为x,表示由x个正立方的方块迭起(如下图,0<=x<=5000).找出所有可能积水的地方(图中蓝色部分),统计它们可能积水 ...

  4. 洛谷U2641 木板面积(area)——S.B.S.

    题目背景 一年一次的夏令营又要开始了,卡卡西和小伙伴们早就做好了准备,满心期 待着这趟快乐之旅.在一个阳光明媚的清晨,卡卡西在老师的带领下来到了这次 夏令营的首站——“神奇木材加工厂” . 题目描述 ...

  5. 洛谷P2820 局域网 (最小生成树)

    题目链接:https://www.luogu.org/problemnew/show/P2820 题目背景 某个局域网内有n(n<=100)台计算机,由于搭建局域网时工作人员的疏忽,现在局域网内 ...

  6. 洛谷1265prim算法求最小生成树

    题目链接:https://www.luogu.com.cn/problem/P1265 最小生成树的prim算法跟dijkstra算法非常像,就是将点分成两个集合,一个是已经在生成树中的点的集合,一个 ...

  7. 【洛谷 p3366】模板-最小生成树(图论)

    题目:给出一个无向图,求出最小生成树,如果该图不连通,则输出orz. 解法:Kruskal求MST. 1 #include<cstdio> 2 #include<cstdlib> ...

  8. 洛谷P1396营救(最小生成树)

    题目描述 “咚咚咚……”“查水表!”原来是查水表来了,现在哪里找这么热心上门的查表员啊!小明感动的热泪盈眶,开起了门…… 妈妈下班回家,街坊邻居说小明被一群陌生人强行押上了警车!妈妈丰富的经验告诉她小 ...

  9. 洛谷P4180 [Beijing2010组队]次小生成树Tree(最小生成树,LCT,主席树,倍增LCA,倍增,树链剖分)

    洛谷题目传送门 %%%TPLY巨佬和ysner巨佬%%% 他们的题解 思路分析 具体思路都在各位巨佬的题解中.这题做法挺多的,我就不对每个都详细讲了,泛泛而谈吧. 大多数算法都要用kruskal把最小 ...

随机推荐

  1. [USACO3.1]最短网络 Agri-Net

    题目背景 Farmer John 被选为他们镇的镇长!他其中一个竞选承诺就是在镇上建立起互联网,并连接到所有的农场.当然,他需要你的帮助. 题目描述 FJ 已经给他的农场安排了一条高速的网络线路,他想 ...

  2. Task06:综合练习

    练习一: 各部门工资最高的员工(难度:中等) 创建Employee 表,包含所有员工信息,每个员工有其对应的 Id, salary 和 department Id. +----+-------+--- ...

  3. .NET 6 亮点之工作负载,它是统一 .NET 的基础

    随着.NET 6 Preview 5的发布,大家认真的看相关文章或者是动手做一个MAUI示例的时候就会碰到一个新概念工作负载(workload),相关规范参见 https://github.com/d ...

  4. 理解Spring:IOC的原理及手动实现

    Spring是一个分层的JavaSE/EE full-stack(一站式) 轻量级开源框架.也是几乎所有Java工作者必须要掌握的框架之一,其优秀的设计思想以及其代码实现上的艺术也是我们需要掌握的. ...

  5. SpringMVC 进阶版

    请求限制 一些情况下我们可能需要对请求进行限制,比如仅允许POST,GET等... RequestMapping注解中提供了多个参数用于添加请求的限制条件 value 请求地址 path 请求地址 m ...

  6. 面试热点|理解TCP/IP传输层拥塞控制算法

    0x00.前言 通过本文你将了解到以下内容: 拥塞控制概念以及其背景 流量控制和拥塞控制的区别与联系 拥塞控制主要过程详解 伙伴们认真学习一下,让offer来得更猛烈些吧! 0x01.TCP/IP协议 ...

  7. 6.17考试总结(NOIP模拟8)[星际旅行·砍树·超级树·求和]

    6.17考试总结(NOIP模拟8) 背景 考得不咋样,有一个非常遗憾的地方:最后一题少取膜了,\(100pts->40pts\),改了这么多年的错还是头一回看见以下的情景... T1星际旅行 前 ...

  8. JAVA设计模式(6:单例模式详解)

    单例模式作为一种创建型模式,在日常开发中用处极广,我们先来看一一段代码: // 构造函数 protected Calendar(TimeZone var1, Locale var2) { this.l ...

  9. 简单聊聊Ehcache缓存

    最近工作没有那么忙,有时间来写写东西.今年的系统分析师报名已经开始了,面对历年的真题,真的难以入笔,所以突然对未来充满了担忧,还是得抓紧时间学习技术. 同事推了一篇软文,看到了这个Ehcache,感觉 ...

  10. 最强阿里巴巴历年经典面试题汇总:C++研发岗

    (1).B树.存储模型 (2).字典树构造及其优化与应用 (3).持久化数据结构,序列化与反序列化时机(4).在无序数组中找最大的K个数? (4).大规模文本文件,全是单词,求前10词频的单词 (5) ...