F. Cheap Robot

给定一个无向连通图,每条边有边权,路过需要消耗对应的电量(边权),有kkk个中心点,

问从a−>ba-> ba−>b,我们最少需要带多少电,设最小为CCC,当通过一条边时,我们的电会减少(当电不够时即不能通过),当经过中心点时我们的电会立刻变为CCC,

比较简单的想法:处理出任意两个中心点对的最短路出来,最后我们只需要得到中心点对的升序kruskalkruskalkruskal最小生成树,然后每次查询两点之间的lcalcalca的权值即可。

我们假设dis[x]dis[x]dis[x]为从xxx到达最近的中心点所需要的电量,

设我们以TTT电量到达了uuu点,那么我们要能够到达终点(注意终点是一个中心点),那么一定有T≥dis[u]T \geq dis[u]T≥dis[u],

也就是说如果离uuu最近的中心点不是终点,那么我们在uuu点的能量可以更新为C−dis[u]C - dis[u]C−dis[u],且有C−dis[u]≥TC - dis[u] \geq TC−dis[u]≥T,

如果与uuu直接相连的边为vvv,要能够到达vvv,那么一定有C−dis[u]≥Wu,vC - dis[u] \geq W_{u, v}C−dis[u]≥Wu,v​,Wu,vW_{u, v}Wu,v​是边权,

同时要使能从vvv到达终点,那么C−dis[u]−Wu,v≥dis[v]C - dis[u] - W_{u, v} \geq dis[v]C−dis[u]−Wu,v​≥dis[v]也同样成立,也就是有C≥dis[u]+dis[v]+wu,vC \geq dis[u] + dis[v] + w_{u, v}C≥dis[u]+dis[v]+wu,v​,

满足上面的式子,我们才可能通过一条边,然后从某条边走向终点,

所以我们可以把原本的一条边的边权转化为Wu,v=Wu,v+dis[u]+dis[v]W_{u, v} = W_{u, v} + dis[u] + dis[v]Wu,v​=Wu,v​+dis[u]+dis[v],跑一个升序kruskalkruskalkruskal最小生成树,找lcalcalca权值即可

#include <bits/stdc++.h>using namespace std;typedef long long ll;const int N = 1e6 + 10;int n, nn, k, m, q, ff[N];ll value[N], dis[N];int head[N], vis[N], nex[N], to[N], cnt = 1;int fa[N], dep[N], sz[N], top[N], son[N], id[N], tot;struct Res {int u, v;ll w;void read() {scanf("%d %d %lld", &u, &v, &w);}bool operator < (const Res &t) const {return w < t.w;}
}edge[N];struct Node {int u;ll w;bool operator < (const Node &t) const {return w > t.w;}
};vector<Node> G[N];bool cmp(int x, int y) {return id[x] < id[y];
}int find(int rt) {return ff[rt] == rt ? rt : ff[rt] = find(ff[rt]);
}void add(int x, int y) {to[cnt] = y;nex[cnt] = head[x];head[x] = cnt++;
}void dfs1(int rt, int f) {fa[rt] = f, dep[rt] = dep[f] + 1, sz[rt] = 1, id[rt] = ++tot;for (int i = head[rt]; i; i = nex[i]) {if (to[i] == f) {continue;}dfs1(to[i], rt);sz[rt] += sz[to[i]];if (sz[son[rt]] < sz[to[i]]) {son[rt] = to[i];}}
}void dfs2(int rt, int tp) {top[rt] = tp;if (!son[rt]) {return ;}dfs2(son[rt], tp);for (int i = head[rt]; i; i = nex[i]) {if (to[i] == fa[rt] || to[i] == son[rt]) {continue;}dfs2(to[i], to[i]);}
}int lca(int x, int y) {while (top[x] != top[y]) {if (dep[top[x]] < dep[top[y]]) {swap(x, y);}x = fa[top[x]];}return dep[x] < dep[y] ? x : y;
}void kruskal() {sort(edge + 1, edge + 1 + m);for (int i = 1; i < N; i++) {ff[i] = i;}for (int i = 1, cur = 1; i <= m && cur < n; i++) {int u = find(edge[i].u), v = find(edge[i].v);if (u ^ v) {cur++, nn++;ff[u] = ff[v] = nn;value[nn] = edge[i].w;add(nn, u), add(nn, v);}}dfs1(nn, 0), dfs2(nn, nn);
}void Dijkstra() {priority_queue<Node> q;memset(vis, 0, sizeof vis);memset(dis, 0x3f, sizeof dis);for (int i = 1; i <= k; i++) {q.push({i, 0});dis[i] = 0;}while (q.size()) {int u = q.top().u;q.pop();if (vis[u]) {continue;}vis[u] = 1;for (auto to : G[u]) {if (dis[to.u] > dis[u] + to.w) {dis[to.u] = dis[u] + to.w;q.push({to.u, dis[to.u]});}}}
}int main() {// freopen("in.txt", "r", stdin);// freopen("out.txt", "w", stdout);// ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);scanf("%d %d %d %d", &n, &m, &k, &q);nn = n;for (int i = 1; i <= m; i++) {edge[i].read();G[edge[i].v].push_back({edge[i].u, edge[i].w});G[edge[i].u].push_back({edge[i].v, edge[i].w});}Dijkstra();for (int i = 1; i <= m; i++) {edge[i].w += dis[edge[i].u] + dis[edge[i].v];}kruskal();while (q--) {int u, v;scanf("%d %d", &u, &v);printf("%lld\n", value[lca(u, v)]);}return 0;
}

F. Cheap Robot(kruskal 重构树)相关推荐

  1. AGC002(D~F)【Kruskal重构树,博弈论,dp】

    正题 AT1998 [AGC002D] Stamp Rally[Kruskal重构树,倍增] https://www.luogu.com.cn/problem/AT1998 题目大意 给出nnn个点m ...

  2. 洛谷P4768 [NOI2018]归程(Kruskal重构树)

    题意 直接看题目吧,不好描述 Sol 考虑暴力做法 首先预处理出从$1$到每个节点的最短路, 对于每次询问,暴力的从这个点BFS,从能走到的点里面取$min$ 考虑如何优化,这里要用到Kruskal重 ...

  3. kruskal 重构树(讲解 + 例题)

    kruskal重构树 如何建树 模仿kruskalkruskalkruskal,先将所有边排序. 依次遍历每一条边,如果这条边的两个节点(u,vu, vu,v)不在同一个连通块里面, 则新建一个nod ...

  4. Network 黑暗爆炸 - 3732 倍增lca || Kruskal重构树

    传送门 文章目录 题意: 思路: 题意: 思路: 两点间最长边最小值一定是最小生成树上两点间的最大值,这个比较容易证,就不多说了. 知道这个结论后, 我们直接跑一个KruskalKruskalKrus ...

  5. [ONTAK2010] Peaks加强版 (kruskal重构树+主席树+倍增)

    Peaks description solution code description 在Bytemountains有N座山峰,每座山峰有他的高度h_i 有些山峰之间有双向道路相连,共M条路径,每条路 ...

  6. [NOI2018] 归程(线段树维护并查集的可持久化/kruskal重构树,倍增+dijkstra最短路)

    [NOI2018] 归程 description solution1 code1 solution2 code description 题目描述 本题的故事发生在魔力之都,在这里我们将为你介绍一些必要 ...

  7. 【kruskal重构树】【主席树】werewolf 狼人(P4899)

    正题 P4899 题目大意 给你一个图,对于每次询问Si,Ei,Li,RiS_i,E_i,L_i,R_iSi​,Ei​,Li​,Ri​,回答从SiS_iSi​走到EiE_iEi​,是否存在路径满足前面 ...

  8. LOJ.2865.[IOI2018]狼人(Kruskal重构树 主席树)

    LOJ 洛谷 这题不就是Peaks(加强版)或者归程么..这算是\(IOI2018\)撞上\(NOI2018\)的题了? \(Kruskal\)重构树(具体是所有点按从小到大/从大到小的顺序,依次加入 ...

  9. NOI2018 Day1 归程(Kruskal重构树)

    目录 NOI2018 Day1 return 题解 AC代码: NOI2018 Day1 return 题解 作为NOI Day1 的T1,这道题目还是比较清真的(虽然自己在同步赛的时候只打了70分的 ...

最新文章

  1. Dash:程序员的好帮手(转载)
  2. ARTS打卡计划第四周-TIPS-自定义一个LikeFilter
  3. apache php 调优_Apache的性能优化(二)
  4. IBM p5服务器上的虚拟 分享,IBMp5服务器系统虚拟技术详解
  5. asp获取ftp服务器目录并显示_用 Python 快速实现 HTTP 和 FTP 服务器
  6. leetcode 714. Best Time to Buy and Sell Stock with Transaction Fee | 714. 买卖股票的佳最时机含手续费(递归->傻缓存->dp)
  7. C#:ref和out的联系及区别。
  8. yum 查看java版本_如何查找YUM安装的JAVA_HOME环境变量详解
  9. 文件I/O(不带缓冲)之read函数
  10. ラブ・ストーリーは突然に(突然發生的愛情故事)歌詞
  11. 笔记本摄像头频闪频灭
  12. 记录遇到的web前端开发面试题(八股文)
  13. 立体声音频效果插件:TBProAudio ST1 for Mac
  14. 网易2017校招合唱团
  15. MFC 资源脚本问题:fatal error CVT1100: 资源重复。类型: AFX DIALOG LAYOUT
  16. steam linux 安装目录,如何在Ubuntu中安装Steam | MOS86
  17. 【从蛋壳到满天飞】JS 数据结构解析和算法实现-Arrays(数组)
  18. 【多目标跟踪论文阅读笔记——JDE(Towards Real-Time Multi-Object Tracking)】
  19. 关于命令执行Bypass的一些思路
  20. python中for循环缩进_跟小白学Python数据分析——For循环

热门文章

  1. 年月跨度_建筑结构丨国内跨度最大的张弦桁架工程——合肥滨湖国际会展中心二期首榀桁架滑移成功...
  2. 软件项目组织管理(六)项目时间管理
  3. 奇妙的曲线--希尔伯特曲线
  4. 如何优雅地向导师/老板表示:“上周工作没什么进展”?
  5. 每日一笑 | 床上还是桌上,你总得选一样~
  6. 有了它,从此成为自带BGM的主角~
  7. 10kv电压互感器型号_电压互感器型号大全
  8. python让函数抛出异常,是否有任何对象可以使str()函数在python中抛出错误或异常?...
  9. 下列选项中 采用边界值平滑_数据挖掘期末考题(答案).doc
  10. win7美化_Potplayer64位美化版,无棒子的tv推送