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

只有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,n103,m2×103:

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

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

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

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

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

但后面再仔细一想,就算这是的答案会被 iii 更新,但是后面一定会枚举到 xxx,显然u→x→vu\rightarrow x\rightarrow vuxv 会比以前的路径少了 (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) 中的点 xxxvvv 相连【在 vvv 连通块里面】 ,或,N(v)N(v)N(v) 中的点 yyyuuu 相连【在 uuu 连通块里面】

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

如果直接枚举 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)xN(u),xq(v)x−ux-uxu 之间的边还没有加入。

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

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

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

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

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

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

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

    这样就处理了挂在 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-wuw 的边权不是第二大。原本 u−xu-xux 的一条边,变成 w−xw-xwx 的一条边。

所以上面的形如 x−ux-uxu :不一定表示原先加入的 mmm 条边就是 x−ux-uxu,而是可能通过 x−a−b−c−...−ux-a-b-c-...-uxabc...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);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/316893.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

# CF1572B Xor of 3(构造)

解析 你CF还是你CF 省选刷到2017再往前不是很想做了&#xff0c;就来CF玩一玩。 再次感受到被CF浅颜色构造虐的快感。 本题靠着各种乱搞特判在WA了无数次之后艹过去了。 根本没有什么正确性的玄学做法&#xff0c;但是看CF数据似乎把 nnn 较小的所有情况全都pia到数据里了&…

NET Core微服务之路:简单谈谈对ELK,Splunk,Exceptionless统一日志收集中心的心得体会...

前言日志&#xff0c;一直以来都是开发人员和运维人员最关心的问题。开发人员可通过日志记录来协助问题定位&#xff0c;运维人员可通过日志发现系统隐患&#xff0c;故障等定位问题。如果你的系统中没有日志&#xff0c;就像一个断了线的风筝&#xff0c;你永远不知道它会的落…

【无码专区2】序列划分(数学)

有std&#xff0c;但是没有自我实现&#xff0c;所以是无码专区 description 完全由数字组成的字符串 sss&#xff0c;划分成若干段&#xff0c;每一段看成一个十进制的数&#xff08;允许前导零&#xff09;求有多少种划分方法使得相邻两个数至少一个是 DDD 的倍数。对 1097…

Rinne Loves Edges

Rinne Loves Edges 题意&#xff1a; 有n给点&#xff0c;m个边&#xff0c;每个边有边权&#xff0c;给你一个点S&#xff0c;问最少花多少代价&#xff0c;可以让叶子节点无法与S点连通 题解&#xff1a; dp[u]:表示u到叶子节点的最短费用的和 dp[u]min(dp[v],w); 代码&…

.NET Core 中的 Generic Host快速使用指南

本文以自己在工作中学习和使用.net core generic-host 作一个总结。前言在创建的ASPNETCORE项目中&#xff0c;我们可以在Main()中看见&#xff0c;我们通过IWebHostBuild创建了一个IWebHost&#xff0c;而微软提供了WebHost.CreateDefaultBuilder(args)来帮助我们更轻松得创建…

CF1580B Mathematics Curriculum(笛卡尔树、树形dp)

解析 比较巧妙的一道题。 难点在于对题意的转化。 关键性质&#xff1a;符合要求的点等价于与笛卡尔树上深度为 mmm 的点。 原因也较为显然&#xff0c;考虑一个特定的点 xxx&#xff0c;当枚举全局最大值时&#xff0c;其会对 xxx 产生贡献&#xff0c;且最大值另一侧就和 xx…

CF1368G Shifting Dominoes(扫描线求矩阵的并集)

CF1368G Shifting Dominoesproblemsolutioncodeproblem 题目链接 solution 求的是最后棋盘本质不同的个数&#xff0c;而本质不同等价于两个空格位置不同。 如果想要移动一个多米诺骨牌&#xff0c;要求长边上下方有空位。 移动可以看成空位的移动。 所以我们考虑把一个 …

吉吉王国(二分+树形dp)

吉吉王国 题意&#xff1a; n个点&#xff0c;m个边&#xff0c;有边权&#xff0c;现在要求叶子节点无法与1号点连通&#xff0c;要求切断的总长度不能超过m&#xff0c;且切断的最长的长度尽可能断 题解&#xff1a; 题意的前半部分可以确定是树形dp&#xff0c;后半部分…

P3239 [HNOI2015]亚瑟王(期望)

解析 显然可以利用期望的线性性对每张牌单独计算贡献。 现在的关键就是如何求出每张牌被使用的概率。 考虑第 iii 张牌&#xff0c;如果它的前面 [1,i−1][1,i-1][1,i−1] 中有 jjj 张牌被使用&#xff0c;那么它被使用的概率就是 1−(1−pi)r−j1-(1-p_i)^{r-j}1−(1−pi​)…

微软一顿操作猛如虎,PowerShell 排名直线上升

近日&#xff0c;TIOBE 发布了 2019 年 3 月编程语言排行榜&#xff0c;PowerShell 首次进入到了榜单的 Top 50 中&#xff0c;排在第 45 位。PowerShell 是运行在 Windows 操作系统上实现对系统以及应用程序进行管理自动化的命令行脚本环境。&#xff08;PowerShell 排在了 TI…

CF1237F Balanced Domino Placements(dp+组合计数)

CF1237F Balanced Domino Placementsproblemsolutioncodeproblem 题目链接 solution 骨牌横着放会占用一行两列&#xff0c;骨牌竖着放会占用两行一列。 问题可以抽象为&#xff1a;每次可以选择连续的两行放 AAA&#xff0c;或选一行放 BBB&#xff1b;每次可以选一列放 B…

AcWing 201. 可见的点

AcWing 201. 可见的点 题意&#xff1a; 题解&#xff1a; 我们先说结论:坐标(i,j)&#xff0c;如果i和j互质&#xff0c;说明该坐标为可见 为什么&#xff1f; 我们想想什么样的坐标可见&#xff0c;什么样的会被挡住。光线是一个直线&#xff0c;在同一个直线上的点会被第一…

模板:LGV引理(线性代数)

所谓LGV引理&#xff0c;就是解决LGV问题的引理。 &#xff08;逃&#xff09; 前言 上联&#xff1a;古有学完SAM学PAM&#xff1b; 下联&#xff1a;今有学完Polya学LGV&#xff1b; 横批&#xff1a;小清新。 常被用于有向图不交路径计数问题。&#xff08;废话&#xff…

ocelot 自定义认证和授权

Intro最近又重新启动了网关项目&#xff0c;服务越来越多&#xff0c;每个服务都有一个地址&#xff0c;这无论是对于前端还是后端开发调试都是比较麻烦的&#xff0c;前端需要定义很多 baseUrl&#xff0c;而后端需要没有代码调试的时候需要对每个服务的地址都收藏着或者记在哪…

CF765F Souvenirs(势能线段树)

CF765F Souvenirsproblemsolutioncodeproblem 题目链接 solution 这个势能线段树简直是太巧妙了&#xff01;&#xff01;&#xff01;( ఠൠఠ )&#xff89; 将询问按右端点升序离线下来。 对于每一个右端点 rrr&#xff0c;维护 ansimin⁡{∣ai−aj∣,j∈[i,r]}ans_i\m…

P4849 寻找宝藏(模板:四维偏序)

stable_sort 保平安。 解析 dp方程显而易见&#xff0c;关键就是如何进行这个四维偏序的转移。 考虑三维偏序&#xff08;比如拦截导弹&#xff09;我们是如何做的&#xff1f; 先按照第一维排序&#xff0c;然后分治解决前一半&#xff0c;接下来把前一半的第一维看成0&…

AcWing 220. 最大公约数

AcWing 220. 最大公约数 题意&#xff1a; 题解&#xff1a; 题目就变成了AcWing 201. 可见的点 当然有微调&#xff0c;因为可见的点里面是从0开始&#xff0c;本题从1开始&#xff0c;所以本题中phi[1]认为是0 AcWing 201. 可见的点的题解 代码&#xff1a; #include<b…

2021 CSP-S 游记

2021CSP-S游记 从国庆过后就开始停课&#xff0c;确实面对的压力和挑战很大。 这段时间真的就是完全没有去想文化课那边的事。 越接近考试时间&#xff0c;模拟赛就越密集&#xff0c;最近大家都在互测。 蛮清楚自己的水平的&#xff0c;而且偶尔还是能考得不错&#xff0c…

欧拉函数(简单介绍+例题)

Acwing视频讲解 欧拉函数&#xff1a;正整数n&#xff0c;欧拉函数是小于n的正整数中与n互质的数的数目 Np1a1 * p1a2 * p1a3 * …* p1ak 如果pj是i的最小质因子 红色区域一样 经推导得&#xff1a;phi[i * pj] phi[i] * pj 如果pj不是i的最小质因子 经推导&#xff1a;phi[…

P5303 [GXOI/GZOI2019]逼死强迫症(斐波拉契、矩阵乘法)

解析 非常妙的一个题&#xff0c;感受到了斐波拉契优美的归纳性质。 首先&#xff0c;不难发现只要两个1*1的位置固定&#xff0c;中间的摆法就固定了&#xff0c;而两边的方案都是经典的斐波拉契数列&#xff08;设为 fif_ifi​&#xff09;。 那么枚举中间的间隔再枚举左边…