The 2021 ICPC Asia Shanghai Regional Programming Contest H. Life is a Game 题解 Kruskal重构树

news/2025/3/21 22:24:54/文章来源:https://www.cnblogs.com/quanjun/p/18785947

题目链接:https://codeforces.com/gym/103446/problem/H

题目大意:

人生就是一场游戏。

世界可以看作是 \(n\) 个城市和城市之间 \(m\) 条无向道路的无向连通图。

现在你,生命游戏玩家,将在世界图表上玩生命游戏。最初,您位于第 \(x\) 个城市和第 \(k\) 个社交能力点。你可以通过生活和工作来获得社交能力点数。

具体来说,您可以通过在第 \(i\) 个城市生活和工作来赚取 \(a_i\) 社交能力点数。但在这个问题中,你不能在一个城市重复获得社交能力点数。所以你想环游世界,获得更多的社交能力点数。然而,道路并不容易。具体来说,第 \(i\) 条道路有一个能力阈值 \(w_i\) ,你至少要有 \(w_i\) 的社交能力点数才能通过这条路。此外,通过道路时,您的社交能力点数不会减少,但如果您想通过第 \(i\) 个道路,则至少需要 \(w_i\) 个社交能力点数奥德。正如你所看到的,生活游戏就是重复地生活、工作和旅行。有 \(q\) 个游戏保存。

每次保存游戏时,都会给出初始城市和社交能力点,并且玩家没有在任何城市生活或工作过。现在你,现实生活中的游戏玩家,需要确定在游戏结束时你可以拥有的社交能力点数的最大可能数量,并为每个给定的游戏保存输出它。

解题思路:

Kruskal重构树 基础练习题。

思路参考自官方题解:https://codeforces.com/gym/103446/attachments/download/14828/LiyuuCute.pdf

这里主要要讲一下就是怎么倍增:

在 kruskal 重构的树中,

对于当前节点 \(u\) 来说,设它的父节点是 \(p\),只有在满足 \(u\) 对应的节点权值和 \(+k\) \(\ge\) 节点 \(p\) 对应的边权时,才能从 \(u\) 走到 \(p\)

所以本题的关键体现在代码中的 \(ff\) 数组,

ff[u][i] 表示 \(u\) 能往上(即祖先节点那个方向)走 \(2^i\) 所需的最小的 \(k\) 是多少。

这一部分是我感觉最需要思考的地方(其它感觉都还好)。

示例程序:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 5, maxm = 2e5 + 5;int n, m, q, f[maxn];
int fa[maxn][17], tr[maxn], idx, dep[maxn], val[maxn];
vector<int> g[maxn];void init() {for (int i = 1; i < 2*n; i++) {f[i] = fa[i][0] = i;g[i].clear();}idx = n;
}int find(int x) {return x == f[x] ? x : f[x] = find(f[x]);
}struct Edge {int u, v, w;bool operator < (const Edge &b) const {return w < b.w;}
} e[maxm];void dfs(int u, int d) {dep[u] = d;for (auto v : g[u])dfs(v, d+1);
}void kruskal_build_tree() {init();sort(e, e+m);for (int i = 0; i < m; i++) {int u = e[i].u, v = e[i].v, w = e[i].w;int x = find(u), y = find(v);if (x != y) {int z = ++idx;tr[z] = w;fa[z][0] = z;g[z].push_back(x);g[z].push_back(y);fa[x][0] = fa[y][0] = z;f[x] = f[y] = z;val[z] = val[x] + val[y];}}for (int i = 1; i <= idx; i++)if (fa[i][0] == i)dfs(i, 0);for (int i = 1; i <= 16; i++)for (int u = 1; u <= idx; u++)fa[u][i] = fa[ fa[u][i-1] ][i-1];
}//int cal(int x, int k) { // 暴力cal会TLE
//    while (fa[x][0] != x) {
//        int p = fa[x][0];
//        if (k + val[x] >= tr[p])
//            x = p;
//        else
//            break;
//    }
//    return k + val[x];
//}int ff[maxn][20];
int before_cal() {for (int u = 1; u <= idx; u++) {if (fa[u][0] == u) {ff[u][0] = 2e9;}else {int p = fa[u][0];ff[u][0] = tr[p] - val[u];}}for (int i = 1; i <= 16; i++)for (int u = 1; u <= idx; u++)ff[u][i] = max(ff[u][i-1], ff[ fa[u][i-1] ][i-1]);
}int cal(int x, int k) {for (int i = 16; i >= 0; i--) {if (k >= ff[x][i]) {x = fa[x][i];}}return k + val[x];
}int main() {while (~scanf("%d%d%d", &n, &m, &q)) {for (int i = 1; i <= n; i++) {scanf("%d", val+i);}for (int i = 0; i < m; i++)scanf("%d%d%d", &e[i].u, &e[i].v, &e[i].w);kruskal_build_tree();before_cal();while (q--) {int x, k;scanf("%d%d", &x, &k);int ans = cal(x, k);printf("%d\n", ans);}}return 0;
}

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

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

相关文章

Cursor 使用教程

目录核心功能TabAICHATCOMPOSER@DocsWebGitNotepadCodebase技巧和思路如果Cursor乱改代码怎么办? 核心功能 Tab 这个是Cursor最为强大的功能,使用也很简单,在编写代码的时候,如果出现了灰色的提示词,直接按Tab就可以自动补全了最后的灰色的就是提示词 Cursor的光标预测也很…

C语言学习打卡第二天(2025.3.21)

时间有点少,今天也没学多少,只把指针基础概念学了一下(例如指针变量,下标法等),题也只做了三道。

3.21 学习记录

设计科技查询手机端系统,实现了政策关键字进行模糊匹配查询,点击下方的政策名称,可以打开新窗口,显示政策全文,实现分页查询,分类查询 采用springboot+vue3实现

P8436 【模板】边双连通分量

P8436 【模板】边双连通分量 题目描述 对于一个 \(n\) 个节点 \(m\) 条无向边的图,请输出其边双连通分量的个数,并且输出每个边双连通分量。 输入格式 第一行,两个整数 \(n\) 和 \(m\)。 接下来 \(m\) 行,每行两个整数 \(u, v\),表示一条无向边。 不保证图为简单图,图中可…

SvelteKit 最新中文文档教程(8)—— 部署 Node 服务端

前言 Svelte,一个语法简洁、入门容易,面向未来的前端框架。 从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构…

第四篇:本地私有化部署大模型(Ollama、vLLM、LMDeploy)

魔塔社区平台介绍 量化:将高精度数值转换成低精度表示的过程(通常用于减少模型的内存和提高推理速度) Ollama部署大模型 linux安装miniconda# 下载 Miniconda 安装脚本 wget https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh # 运行安装脚本 bash…

用Adobe Illustrator编辑ArcGIS地图的方法

本文介绍在ArcGIS下属的ArcMap软件中,将绘制好的地图导出为.ai或者.eps格式文件,并在Adobe Illustrator软件中进一步编辑地图,并最终导出为图片格式的结果文件的方法~本文介绍在ArcGIS下属的ArcMap软件中,将绘制好的地图导出为.ai或者.eps格式文件,并在Adobe Illustrator软…

协议版iM蓝号检测,批量筛选iMessages数据,无痕检测是否开启iMessage服务

一、实现iMessage数据检测的两种方式:1.人工筛选,将要验证的号码输出到文件中,以逗号分隔。再将文件中的号码粘贴到iMessage客户端的地址栏,iMessage客户端会自动逐个检验该号码是否为iMessage账号,检验速度视网速而定。红色表示不是iMessage账号,蓝色表示iMessage账号。2…

记录项目调用链路

记录项目调用链路 内容 要理清项目中执行链路的调用关系,可以通过以下工具分类实现,涵盖从代码静态分析到运行时动态追踪的全链路管理:一、代码层调用关系分析 1. 静态代码分析工具PyCallGraph(Python) 生成代码调用关系图,直观展示函数调用链路。 pip install pycallgra…

部署kibana

获取kibana安装包 [root@elk1 ~]# wget https://artifacts.elastic.co/downloads/kibana/kibana-7.17.28-amd64.deb[root@elk1 ~]# ls kibana-7.17.28-amd64.deb kibana-7.17.28-amd64.deb# 安装kibana [root@elk1 ~]# dpkg -i kibana-7.17.28-amd64.deb 配置kibana [root@elk…

多线程程序设计(四)——Balking

本文摘要了《Java多线程设计模式》一书中提及的 Balking 模式的适用场景,并针对书中例子(若干名称有微调)给出一份 C++ 参考实现及其 UML 逻辑图,也列出与之相关的模式。 ◆ 适用场景 当线程访问的共享数据没有准备好时,就放弃后续的操作。 ◆ 解决方案 在临界区中判断共享…

A preLaunchTaskC/C++:g++.exe 生成活动文件已终止,退出代码为1。找到一个有点呆的bug

之前突然弹出这个问题,百思不得其解,今天突然发现,因为之前顺便命名了一个c++文件用来暂时装代码的,名字叫做a.cpp,编译器编译的过程中会生成一个可执行文件叫做a.exe,就冲突了,太傻了:-(