题目链接

CSDN 最近 LaTeX\LaTeXLATE​X 渲染的真的好丑啊,看不下去了,最近只在 CSDN 上发一点公式不那么多的题解了,式子多的我得等 CSDN 这玩意好了再交吧,目前是有一道四边形不等式的/kel

题目大意

给定一张有 nnn 个节点,mmm 条边的无向图,对于任意的 iii(2⩽i⩽n2\leqslant i\leqslant n2⩽i⩽n),请求出在不经过原来 111 节点到 iii 节点最短路上最后一条边的前提下,111 节点到 iii 节点的最短路。

特别地,保证 111 到任何一个点 iii 的最短路都是唯一的。

数据范围 n⩽2×105,m⩽5×105n\leqslant 2\times 10^5,m\leqslant 5\times 10^5n⩽2×105,m⩽5×105。

题解

我们先来挖掘这个题目的绝妙性质,假设我们还不知道最短路唯一这个条件有什么用。但我们发现这个“最短路最后一条边”对于每一个点来说是唯一的,一个点只能对应一条边,一条边也只能对应一个点。证明的话手玩一下就知道不可能存在一条边他既是 xxx 的最后一条,也是 yyy 的最后一条。

因此这个性质告诉我们,这些边组成的一定会是一棵树(不是基环树是因为 111 节点没有这样的边,二是因为不可能存在一个环上所有边都是最短路的最后一条边,也是手玩一下)。我们考虑这个边是怎么求出来的,在最短路中我们不断地去松弛一个节点,如果不能松弛了则这条边就是这个节点最短路上的一条边,而且一定会是最后一条边。

这说明一件事,我们建出来的树显然是一棵最短路径树。这完美的契合了题目最短路唯一的性质,这样建出来的最短路径树也是唯一的。

自己造的板子/kel

接下来我们考虑删除最短路径树上点 xxx 连向他父亲的边。可以证明,假设删除后的最短路有 nnn 条边,那么其中 n−1n-1n−1 条边都一定在最短路径树上,只有一条边是非树边。而且,删除那条边后,这棵树被分成了两个连通块,非树边一定是连通了这两个连通块的。

分割开的连通块有一个是以 xxx 为根节点的,我们令这棵树上一个子节点为 yyy,另一个连通块上一个点为 zzz。令 disidis_idisi​ 表示原图中 111 到 iii 的最短路,由于最短路径树一个优美的性质,这个最短路等于最短路径树上 111 到 iii 的距离(一眼的,根据定义的)。那么删除边后 xxx 的最短路会被表示为 disz+az→y+disy−disxdis_z+a_{z\to y}+dis_y-dis_xdisz​+az→y​+disy​−disx​。经过一点简单观察发现显然 disxdis_xdisx​ 是固定的,因为我们枚举了 xxx,所以我们只需要找到一个最小的 disz+az→y+disydis_z+a_{z\to y}+dis_ydisz​+az→y​+disy​ 即可。

接下来有许多解法:

  1. 类并查集解法。考虑这个最小的 disz+az→y+disydis_z+a_{z\to y}+dis_ydisz​+az→y​+disy​ 可能对多少 xxx 造成贡献。答案是 y→LCA⁡(y,z)y\to \operatorname{LCA}(y,z)y→LCA(y,z) 与 z→LCA⁡(y,z)z\to\operatorname{LCA}(y,z)z→LCA(y,z) 上的所有点。显然如果不在这条范围上,zzz 就不可能位于别的连通块。但是很显然排序后一个点只会被更新一次,更新完了就是最优的,所以我们用一种类似跳 LCA 的做法,修改并查集,即可得到答案。
  2. 树剖解法。不用排序了,直接插,更加暴力/hanx

总时间复杂度 O((m+n)log⁡n)\mathcal{O}((m+n)\log n)O((m+n)logn),复杂度瓶颈在排序和 dijkstra 上。

这玩意卡 SPFA,不知道为什么很多最短路径树的题目都喜欢卡 SPFA/lh

代码

int head[N],cnt,dep[N],ans[N],dis[N],vis[N],now[N],tot,n,m;
struct node{int x,y,z;}f[N],p[N];
void add(int x,int y,int z){a[++cnt].to=y;a[cnt].nxt=head[x];a[cnt].l=z;head[x]=cnt;
}
void get_ans(int x,int y,int z){if(x==y) return;if(dep[x]<dep[y]) swap(x,y);if(!ans[x]) ans[x]=z-dis[x];get_ans(now[x],y,z);
}
void dijkstra(){for(register int i=1;i<=n;i++) dis[i]=inf,vis[i]=false;dis[1]=0;priority_queue<pair<int,int> > q;q.push(make_pair(0,1));while(!q.empty()){int x=q.top().sec;q.pop();if(vis[x]) continue;vis[x]=true;for(register int i=head[x];i;i=a[i].nxt){int y=a[i].to;if(dis[y]>dis[x]+a[i].l){now[y]=x;dis[y]=dis[x]+a[i].l;if(!vis[y]) q.push(make_pair(-dis[y],y));}}}
}
int find(int x){if(dep[x]) return dep[x];return dep[x]=find(now[x])+1;
}
bool cmp(node x,node y){return x.z<y.z;}
signed main(){n=read(),m=read();now[1]=1,dep[1]=1;for(register int i=1;i<=m;i++){int x=read(),y=read(),z=read();add(x,y,z);add(y,x,z);f[i]=(node){x,y,z};}dijkstra();for(register int i=1;i<=n;i++) dep[i]=find(i);for(register int i=1;i<=m;i++){if(dis[f[i].x]>dis[f[i].y]) swap(f[i].x,f[i].y);if(dis[f[i].x]+f[i].z==dis[f[i].y]) continue;p[++tot]=(node){f[i].x,f[i].y,dis[f[i].x]+dis[f[i].y]+f[i].z};}sort(p+1,p+tot+1,cmp);for(register int i=1;i<=tot;i++) get_ans(p[i].x,p[i].y,p[i].z);for(register int i=2;i<=n;i++){if(!ans[i]) printf("-1\n");else printf("%lld\n",ans[i]);}// retururnr 1;
}

【最短路径树】 [USACO09JAN]Safe Travel G相关推荐

  1. CSP认证201609-4 交通规划[C++题解]:最短路径树、dijkstra求单源最短路、递推思想

    题目分析 来源:acwing 分析: 这题是最短路树.保持原图中所有点到根结点的最短距离不变,然后在原图中选择一些边,使所有点连通的最短路是多长. 最短路径树,是一种使用最短路径算法生成的数据结构树. ...

  2. [USACO09JAN]安全出行Safe Travel

    [USACO09JAN]安全出行Safe Travel 题目描述 Gremlins have infested the farm. These nasty, ugly fairy-like creat ...

  3. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)

    题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...

  4. 最小生成树、最短路径树

    一.最小生成树与最短路径树的区别 最小生成树能够保证整个拓扑图的所有路径之和最小,但不能保证任意两点之间是最短路径. 应用如网络部线,把所有的电脑(服务器?)都连起来用的网线(光纤?)最少,即用最小的 ...

  5. bzoj 4016: [FJOI2014]最短路径树问题

    Description 给一个包含n个点,m条边的无向连通图.从顶点1出发,往其余所有点分别走一次并返回. 往某一个点走时,选择总长度最短的路径走.若有多条长度最短的路径,则选择经过的顶点序列字典序最 ...

  6. 最短路径树(SPT)介绍及matlab代码

    文章目录 前言 一.最短路径树是什么? 二.最短路径树的算法 1.Dijkstra算法(我比较常用和喜欢的算法) 2.Floyd算法 总结 前言   最短路径树是路由算法设计中常用到的一种树,往往我们 ...

  7. [K短路 可持久化堆 最短路径树] JDFZ 2978 第k短路(强)

    链接:https://oj.jdfz.com.cn/oldoj/problem.php?id=2978 鼎爷的[课件]堆的可持久化和k短路 其中每条边的新权值可以形象的理解为走这条边要多花的代价 然后 ...

  8. 点分治问题 ----------- P2993 [FJOI2014]最短路径树问题 [最短路径树+点分治+采坑]

    题目链接 解题思路: 首先我们知道最小路径树实际上就是Dijkstra算法在找最短路的时候转移的过程就是一个最短路径树. 那么我们就可以先跑个最短路,记录一下各个最短路的路径.然后就是很裸的点分治.分 ...

  9. HDU 5385 The path(贪心、构造、最短路径树)

    HDU 5385 题目大意:给定一个图,dis表示第i个点到1点的最短路,dis1=0,给有向图上的边赋权值(1~n)满足dis1<dis2<dis3<--<disk>d ...

最新文章

  1. 这样玩《TmoLand》包你收益最大化
  2. Java对象的实例化
  3. ESX 4 不能使用SSH登录的解决
  4. Windows下删除.svn文件夹的最简易方法
  5. spring+hibernate的配置
  6. php fpm 不写errorlog,PHP-FPM不写入错误日志
  7. Heritrix 3.1.0 源码解析(六)
  8. 使用缓存防击穿,解决微信”被动回复用户消息”重试回复问题
  9. Flash游戏开发实战(一)
  10. MediaPlayer 播放视频的方法
  11. loadrunner脚本录制为空的解决方法
  12. mysql 命令行怎么格式化_dbForge Data Compare for MySQL入门教程:通过命令行格式化代码...
  13. 【前端性能优化】不用 setTimeout 实现防抖
  14. 如何处理“转换数据类型错误”错误?
  15. iPhone上编辑html,在iphone上重新格式化一个简单的html页面
  16. 多线程跑调度_java多线程中的调度策略
  17. java 获取本机mac地址并转为字符串
  18. 每周荐书:JVM、Nginx、小程序(评论送书)
  19. GreenDao的学习和使用
  20. C++/CLI C#字符串转为C++字符串正确写法

热门文章

  1. 速腾雷达录包方法(32线)
  2. python安装cv2模块的方法_Python opencv模块cv2安装和部分函数使用
  3. 软件测试进阶之2——沉下心来思考
  4. Collection
  5. Java实现单次转账到支付宝账户(新版接口)(SpringBoot)
  6. 使用eBPF将网络功能Offload到网卡
  7. 学习 Python 可以快速赚钱吗?
  8. 状态码的含义,以及HTTP中常见的状态码
  9. getBytes()方法详解
  10. 华为云GaussDB(for Redis)GaussDB(for Redis)全面对比Codis