European Championship 2025 E - Porto Vs. Benfica

news/2025/4/2 11:00:19/文章来源:https://www.cnblogs.com/YipChipqwq/p/-/2068E

E. Porto Vs. Benfica

题意说的很清楚了,这里就不再过多阐述。

有个很直接了当的算法就是,枚举每一个点,并且枚举它相邻的一条边,从 \(1\) 跑到这个点的最短路加上这个点不经过这条边到 \(n\) 的最短路之和。

\(dist(u, \, v)\) 表示 \(u, \, v\) 之间的最短路,\(g(u, \, v)\) 表示从 \(u\) 开始不经过边 \((u, \, v)\) 到达 \(n\) 的最短路,一个合法的答案显然为 \(dist(1, \, u) + \max\{g(u, \, v)\}\)

显然警察希望割边的时候是费用最大,所以我们用 \(g(u)\) 表示所有 \(g(u, \, v)\) 的最大值,如果设 \(f(u)\) 表示从 \(u\) 点开始,满足题意的答案的最小值,那么如果 \(u, \, v\) 相连,枚举所有 \(u\) 的临接点 \(v\),我们有 \(f(u) = \min\limits_{(u, \, v) \in G}\{\max\{f(v) + 1, \, g(u)\}\}\),由于我们想要更新的 \(f(u)\) 尽可能小,所以我们可以贪心的拿 \(f(v)\) 更小的点去更新,当一个未使用的点是最小的时候,我们称这个点是确定的,我们用这个最小的点去更新其他未确定的点,方法类似 Dijkstra,因此这一步是好做的,问题是如何得到 \(g\) 的值。

考虑从 \(n\) 开始的一颗 BFS 树,这颗树的树边是最短路径必须经过的,所以警察割边一定只会割树边,所以我们希望走一个横叉边来尽可能达到最短,显然叶子节点的值一定为所有能走的横叉边中价值的最小值,为了不让向上更新时出现不合法的情况,我们给每个点记录 \((d, \, v)\) 的二元组,表示从当前节点 \(u\) 走向 \(v\) 花费为 \(d\),显然我们可以用一个小根堆存储这些二元组,答案就恰好为堆顶。

如果 \(u\) 在树上含有儿子 \(v\),我们显然可以走向 \(v\) 再走横叉边,所以需要把儿子的 \((d, \, v)\) 更新到父亲,价值为 \((d + 1, \, v)\),此时做启发式合并,用标记永久化维护,我们向上合并的时候,可能 \((d, \, v)\)\(v\) 会变成 \(u\) 子树的一个节点,这是不合法的,我们可以利用并查集维护此信息,当堆顶不合法时弹掉即可。

综上,复杂度主要来源于启发式合并,总时间复杂度 \(O(n\log^2{m})\)

参考代码

#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 2e5 + 10, INF = 0x3f3f3f3f;
int n, m;
int dist[N], f[N], g[N], p[N], delta[N];
vector<int> edge[N], tree[N];
map<PII, int> in_tree;
priority_queue<PII, vector<PII>, greater<PII>> h[N];int find(int x) {if (p[x] != x) p[x] = find(p[x]);return p[x];
}void bfs(int S) {vector<int> st(n + 1);queue<int> q;q.push(S), st[S] = 1;while (q.size()) {int u = q.front();q.pop();for (auto v : edge[u]) {if (st[v]) continue;dist[v] = dist[u] + 1;tree[u].push_back(v);in_tree[{u, v}] = in_tree[{v, u}] = 1;st[v] = 1, q.push(v);}}
}void dfs(int u) {for (auto v : edge[u]) {if (!in_tree.count({u, v})) {h[u].push({dist[v] + 1, v});}}for (auto v : tree[u]) {dfs(v);delta[v] ++ ;p[find(v)] = p[find(u)];if (h[u].size() < h[v].size()) swap(h[u], h[v]), swap(delta[u], delta[v]);while (h[v].size()) h[u].push({h[v].top().first + delta[v] - delta[u], h[v].top().second}), h[v].pop();}while (h[u].size() && find(u) == find(h[u].top().second)) h[u].pop();if (h[u].size()) g[u] = h[u].top().first + delta[u];else g[u] = INF;
}void dijkstra(int S) {vector<int> st(n + 1);memset(f, 0x3f, sizeof f);priority_queue<PII, vector<PII>, greater<PII>> heap;f[S] = 0, heap.push({f[S], S});while (heap.size()) {int u = heap.top().second;heap.pop();if (st[u]) continue;st[u] = 1;for (auto v : edge[u]) {if (f[v] > max(g[v], f[u] + 1)) {f[v] = max(g[v], f[u] + 1);heap.push({f[v], v});}}}
}void solve() {cin >> n >> m;for (int i = 1; i <= n; i ++ ) p[i] = i;for (int i = 1; i <= m; i ++ ) {int a, b;cin >> a >> b;edge[a].push_back(b);edge[b].push_back(a);}bfs(n);dfs(n);dijkstra(n);if (f[1] != INF) cout << f[1] << "\n";else cout << "-1\n";
}int main() {ios::sync_with_stdio(false);cin.tie(0), cout.tie(0);int T = 1;// cin >> T;while (T -- ) solve();return 0;
}

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

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

相关文章

WebSocket调试神器对决:Apipost凭何碾压Apifox?

你以为所有API工具都能玩转WebSocket? 当你的APP需要实时股票行情推送,当你的游戏要处理千人同屏交互,当你的IM系统必须保障消息零延迟——传统HTTP协议的"一问一答"模式瞬间破功。此刻WebSocket协议才是真正的救世主,这个全双工通信协议能让客户端与服务器建立&…

一年前的无心之举,一年后我想要将其做的更好——公众号开通。

大家好,答应的事情要做到。 我是晚秋,我在这里,这是我的公众号。 一年前我想把学过的技术,解决得问题都记录下来,帮助更多的人。 日复一日,也放弃过。 但是到今日,忽然看到自己的无心之举帮助了很多刚进入技术这一行的人。 他们迷茫,他们困顿,正如当初的我一样。 谢谢…

用户头像呼吸光环+鼠标悬停旋转放大

用户头像呼吸光环+鼠标悬停旋转放大在 子比主题后台 – 自定义代码 – 自定 CSS 样式代码 里面添加下面代码: /*【用户头像呼吸光环+鼠标悬停旋转放大】开始 */ .avatar{border-radius: 50%; animation: light 4s ease-in-out infinite; transition: 0.5s;}.avatar:hover{tran…

开源守护,智护童年——幼儿园未成年行为与安全智能监控系统

在孩子成长的每一步,安全始终是第一位的。幼儿园作为孩子们探索世界的起点,其安全管理的重要性不言而喻。然而,哭闹、打闹、意外跌倒,甚至外部隐患如陌生人逗留、内部管理疏漏等问题,常常让传统人工监控捉襟见肘。家长们也迫切希望了解孩子在园的点滴,渴望一份安心与信任…

20241220廖补林实验二《Python程序设计》实验报告

实验二 计算器设计 (一)实验内容 设计并完成一个完整的应用程序,完成加减乘除模等运算,功能多多益善。 考核基本语法、判定语句、循环语句、逻辑运算等知识点 (二)实验要求 创建工程项目,使用Python语言实现具体的操作运算,并完成程序调试和运行,代码托管到码云。 我用…

网络基础

一、概念 冲突域设备发送数据会产生冲突的网络范围 集线器的所有接口在同一个冲突域 交换机的每个接口都是一个独立的冲突域寻址IP寻址是寻找目标在某一个范围 MAC寻址是具体寻找某一个设备MTU数据包的最大传输单元 接口收发数据支持的单个包的最大长度 以太网接口默认MTU1500B…

20241309 实验二《Python程序设计》实验报告

20241309 2024-2025-2 《Python程序设计》实验二报告 课程:《Python程序设计》 班级: 2413 姓名: 梅良谦 学号:20241309 实验教师:王志强 实验日期:2025年3月26日 必修/选修: 公选课 一、实验内容 1.设计并完成一个完整的应用程序,完成加减乘除模等运算,功能多多益善。…

【操作系统】进程管理(二)

一、前言之前已经介绍了操作系统的各个模块,现在来具体深入学习操作系统中的进程管理。 二、进程的基本概念在未配置OS的系统中,程序的执行方式是顺序执行,即必须在一个程序执行完成后,才允许另外一个程序执行;在多道程序环境下,则允许多个程序并发执行。也正是程序的并发…

MybatisPlus--持久层接口

IService: Save()boolean save(T entity) //批量插入 boolean saveBatch(Collection<T> entityList) boolean saveBatch(Collection<T> entityList, int vatchSIze)SQL:INSERT INTO user (name, email) VALUES (John Doe, john.doe@example.com)批量SQL:INSERT…

CH58x/CH59x动态修改广播包

前言:在日常使用中我们可能有需要动态修改广播包的情况。从机设备不走连接将一些传感器数据通过广播包显示出来 程序中提供了接口函数进行动态修改不用再先关闭广播再重新开启。/******************************************************************************** @fn …

docker 容器部署nginx+keepalived实现高可用

准备两台机器分别部署nginx和keepalived,事先部署好docker容器环境。主机名 ip地址 部署容器park2-0007 10.9.102.62 nginx+keepalivedpark2-0008 10.9.102.63 nginx+keepalived分别启动两个nginx容器docker run -d \--name my-nginx -p 8005:8005 \-v ./nginxdir/default.c…