只有std,没有自我实现,所以叫做无码专区

description

给一张无向图,多次询问,每次询问两个点之间所有简单路径(不重复经过点)中边权第二大(不是严格第二大)的权值的最小值。

数据范围:10510^5105 级别

我的想法

前 50%50\%50% 的数据 q,n≤103,m≤2×103:q,n\le 10^3,m\le 2\times 10^3:q,n≤103,m≤2×103:

先做一次最小生成树,求出任意两点之间联通的最小边权(某条路径的最大边权值)。

每次询问 (u,v)(u,v)(u,v) ,我直接枚举中间转折点 iii,强制这条路径是 u→i→vu\rightarrow i\rightarrow vu→i→v。【→\rightarrow→ 代指一条路径】

第二大边权就是 (u,i)(u,i)(u,i) 联通路径的最大值和 (v,i)(v,i)(v,i) 联通路径的最大值,二者中的较小值。

旁边的 Oxide\text{Oxide}Oxide 巨佬认为很有可能 u→iu\rightarrow iu→i 和 i→wi\rightarrow wi→w 之间经过了同样的点。

i.e. u→x→i→x→vu\rightarrow x\rightarrow i \rightarrow x\rightarrow vu→x→i→x→v

但后面再仔细一想,就算这是的答案会被 iii 更新,但是后面一定会枚举到 xxx,显然u→x→vu\rightarrow x\rightarrow vu→x→v 会比以前的路径少了 (x,i)(x,i)(x,i) 一段。

路径上的边权最大值一定是不减的

所以多的 (x,i)(x,i)(x,i) 一段只可能使最大边权增大 / 不变。

那么 xxx 的决策一定是不劣于 iii 的决策的。

另有 20%20\%20% 是树:两个点之间只有一条简单路径,可以直接倍增求路径的第二大边权值。

综上,本题自我实现分值应该在 70′70'70′。

solution

类似最小生成树的方法,从小到大加边。

如果加完一条边后,u,vu,vu,v 之间只差一条边联通,那么显然这条边就是第二小,也就是最终的答案。

考虑怎么维护?

设 N(u):N(u):N(u): 与 uuu 有直接边相连,但还没有相连的点的集合【当前枚举边的权值暂时小于等于这些点与 uuu 的权值,最小生成树的写法就还没有加入这些边】

或者理解为:还差一条边就能联通的点的集合

考虑启发式合并,每次合并 u,vu,vu,v 各自所在的连通块。

此时可能出现:N(u)N(u)N(u) 中的点 xxx 与 vvv 相连【在 vvv 连通块里面】 ,或,N(v)N(v)N(v) 中的点 yyy 与 uuu 相连【在 uuu 连通块里面】

这个时候意味着,加上 u−vu-vu−v 这条边后,还差 u−xu-xu−x 或 v−yv-yv−y 这一条边就会使得 u,vu,vu,v 相连,所以 u−vu-vu−v 这条边权就是最后的答案。

如果直接枚举 N(u),N(v)N(u),N(v)N(u),N(v) 则不符合时间限制。

我们可以这么做:

  • 遍历 N(u)N(u)N(u) 的所有点,然后看是否在 vvv 的询问中。

    i.e. 假设 x∈N(u),x∈q(v)x\in N(u),x\in q(v)x∈N(u),x∈q(v) , x−ux-ux−u 之间的边还没有加入。

    此时加入为 u−vu-vu−v 的边。一旦加入完,x→u→vx\rightarrow u\rightarrow vx→u→v就只差 x−ux-ux−u 的一条边。

    所以答案就是现在操作的 u−vu-vu−v 边的边权。

    这样就处理了挂在 vvv 上面的某些 通过 uuu 连通块中某些点和边解决 的询问。

  • 遍历 uuu 里面的所有询问,判断是否在 N(v)N(v)N(v) 中。

    i.e. 假设 x∈q(u)x\in q(u)x∈q(u) , x−vx-vx−v 之间的边还没有加入。

    此时加入为 u−vu-vu−v 的边。一旦加入完,x→v→ux\rightarrow v\rightarrow ux→v→u 就只差 x−vx-vx−v 的一条边。

    所以答案是 u−vu-vu−v 现在这条边的边权。

    这样就处理了挂在 uuu 上面的某些 通过 vvv 连通块中某些点和边解决 的询问。

这么做会发现,虽然是合并两个联通块和处理两个联通块各自挂着的询问,但是枚举的只有一个联通块的信息。

所以启发式合并,就用 N(u)+q(u)N(u)+q(u)N(u)+q(u) 和 N(v)+q(v)N(v)+q(v)N(v)+q(v) 大小比较,选较小的进行枚举。

时间复杂度 O(nlog⁡n)O(n\log n)O(nlogn)

合并具体而言:枚举其中一个较小连通块的信息,进行答案处理。所有挂在 u,vu,vu,v 点的询问和边都重新挂在合并后新连通块的根 www 上。

i.e. 询问 u,xu,xu,x 的答案,合并后相当于问 w,xw,xw,x 的答案,因为反正 u−wu-wu−w 的边权不是第二大。原本 u−xu-xu−x 的一条边,变成 w−xw-xw−x 的一条边。

所以上面的形如 x−ux-ux−u :不一定表示原先加入的 mmm 条边就是 x−ux-ux−u,而是可能通过 x−a−b−c−...−ux-a-b-c-...-ux−a−b−c−...−u ,不断合并,可能代指的是一条简单路径。

参考code

#include <bits/stdc++.h>
using namespace std;#define N 400005#define pb push_back
int fa[N];
struct node {int x, y, z;
} b[N];
int ans[N], n, m, Q;
set<array<int, 2>> q[N];
set<int> e[N];int get(int x) {if (fa[x] == x)return x;return fa[x] = get(fa[x]);
}inline bool cmp(node x, node y) {return x.z < y.z;
}void combine(int x, int y, int val) {for (auto u : e[x]) {while (1) {auto it = q[y].lower_bound({u, -1});if (it == q[y].end() || (*it)[0] != u)break;int id = (*it)[1];ans[id] = val;assert(q[y].count({u, id}));assert(q[u].count({y, id}));q[y].erase(it);q[u].erase({y, id});}}vector<array<int, 2>> delq;for (auto u : q[x]) {if (e[y].count(u[0])) {ans[u[1]] = val;q[u[0]].erase({x, u[1]});delq.pb(u);}}for (auto u : delq)q[x].erase(u);fa[x] = y;for (auto v : e[x]) {assert(e[v].count(x));e[v].erase(x);if (v != y) {e[v].insert(y);e[y].insert(v);}}e[x].clear();for (auto v : q[x]) {assert(v[0] != y);assert(q[v[0]].count({x, v[1]}));q[v[0]].erase({x, v[1]});q[v[0]].insert({y, v[1]});q[y].insert({v[0], v[1]});}q[x].clear();
}int main() {freopen("path.in", "r", stdin);freopen("path.out", "w", stdout);scanf("%d%d%d", &n, &m, &Q);for (int i = 1; i <= n; i++)e[i].clear(), q[i].clear();for (int i = 1; i <= m; i++) {scanf("%d%d%d", &b[i].x, &b[i].y, &b[i].z);e[b[i].x].insert(b[i].y);e[b[i].y].insert(b[i].x);}for (int i = 1; i <= n; i++)fa[i] = i;sort(b + 1, b + 1 + m, cmp);for (int i = 1; i <= Q; i++) {ans[i] = 0;int x, y;scanf("%d%d", &x, &y);if (e[x].count(y)) {ans[i] = 1;continue;}q[x].insert({y, i});q[y].insert({x, i});}for (int i = 1; i <= m; i++) {b[i].x = get(b[i].x), b[i].y = get(b[i].y);if (b[i].x == b[i].y)continue;if (q[b[i].x].size() + e[b[i].x].size() > q[b[i].y].size() + e[b[i].y].size())swap(b[i].x, b[i].y);combine(b[i].x, b[i].y, b[i].z + 1);}for (int i = 1; i <= Q; i++)printf("%d\n", ans[i] - 1);
}

【无码专区1】简单路径的第二大边权(启发式合并+最小生成树)相关推荐

  1. 【无码专区5】01串(大讨论+构造)

    因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dl ...

  2. 【无码专区8】三角形二维数点——计数有多少个给定点落在三角形区域内

    因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dl ...

  3. 【无码专区12】子集和(背包dp)

    此题已自我实现,但仍归于无码专区 本题在考场上就过了,所以难度并不高,发现性质即可. problem 有 nnn 个正整数 a1,a2,...,ana_1,a_2,...,a_na1​,a2​,... ...

  4. 【无码专区10】第K大查询(双向链表 /主席树+st表)

    已自我实现,但还是归入无码专区序列.哈哈哈哈哈 对于my idea部分,我的每一个想法都实现了,可供参考. problem 给定一个 1∼n1\sim n1∼n 的排列和 kkk,求所有 r−l+1≥ ...

  5. 【无码专区7】括号序列(思维)

    因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dl ...

  6. 【无码专区13】最小公倍数(线段树)

    因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 my idea顾名思义,记录了我的整个思维过程,以及自己部分实现细节口胡,还有期望分数 solution才是dls正解,但是因为只 ...

  7. 【无码专区11】异或2(结论 / 推式子 + 哈希hash + 大整数高精度 加减乘除重载考察)

    本题已自我实现.但仍归于无码专区 problem 求 ∑i=1n−1i⨁(n−i)\sum_{i=1}^{n-1}i\bigoplus (n-i)∑i=1n−1​i⨁(n−i). 20%,n≤1e6; ...

  8. 【无码专区9】序列统计(带权并查集 + 前缀和建边 + dp)

    因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dl ...

  9. 【无码专区6】球与盒子(数学线性筛)

    因为只有std,没有自我实现,所以是无码专区 主要是为了训练思维能力 solution才是dls正解,但是因为只有潦草几句,所以大部分会有我自己基于正解上面的算法实现过程,可能选择的算法跟std中dl ...

最新文章

  1. 文本分类解决方法综述
  2. php设计模式简单代码,PHP设计模式(1)工厂模式
  3. new操作符到底干了什么?
  4. 数据库如何进行索引优化
  5. @Autowired作用在普通方法上
  6. 如何禁用特定css_通过CSS追踪用户
  7. Unity3D基础31:脚本生命周期
  8. python实现抢劵_双十一福利丨机械键盘、蓝牙音箱送送送!Python/UI/Unity多场微课解剖双十一套路!...
  9. 蓝桥杯2017年第八届C/C++省赛C组第一题-贪吃蛇长度
  10. webpack-dev-server启动后, localhost:8080返回index.html的原理
  11. proteus软件安装包8.11
  12. R语言(四)——十折交叉验证/机器学习回归【决策树(随机森林)、组合方法、SVR】
  13. linux系统无法启动提示give root password for maintenance的多种解决方法
  14. endnote参考文献排版_如何用 EndNote 编辑适合投稿杂志的参考文献格式
  15. 操作系统进程状态和状态转换详解
  16. cena使用自定义校检器
  17. 原假设“截距为0”双侧检验P值是多少_假设检验——这一篇文章就够了
  18. ssh连接远程服务器自动断开解决
  19. 【观察】软件行业创新进入“新周期”,如何在变局中开新局?
  20. gz解压(gz解压不了)

热门文章

  1. python多进程间通信_python多进程间通信代码实例
  2. sql语句ding_mybatis plus 写sql语句
  3. 罗马数字转换成数字java_C趣味编程百例(31)将阿拉伯数字转换为罗马数字
  4. epublib java_使用Epublib处理epub文件 | 学步园
  5. 机器学习与气象数据_气象大数据与机器学习联合实验室 大数据和气象的“联姻”...
  6. 机器学习之数据预处理——特征编码(标签编码,独热编码)
  7. 计算机网络:如何传输一条数据(详解)
  8. java 解析 manifest_解析AndroidManifest.xml之AXMLParser.java | 学步园
  9. [PAT乙级]1038 统计同成绩学生
  10. [蓝桥杯2017决赛]数位和-模拟(水题)