Problem H. saki 酱 saki 酱 saki 酱 saki 酱(树的直径)
Problem H. saki 酱 saki 酱 saki 酱 saki 酱
输入文件: standard input
输出文件: standard output
时间限制: 1 second
内存限制: 256 MB
小祥,来组 Ave Mujica 吧
我们一直在一起吧
我真的很幸福
我想把人生,全部都给你
初音在剧场阴暗的爬行,她要找回只属于她祥子
剧场的结构是一棵有 n 个节点的树,树的所有边权都为 1。初音会向小祥发出 q 次邀请。每次邀请
给出初音在的初始位置 v 和她能看到的距离 k, 如果祥子在树上任何一个节点都能被初音看见,那她就会
同意加入 Mujica,否则会拒绝。
输入格式
第一行给定树的节点数 n(2 ⩽ n ⩽ 5 × 105)
接下来 n − 1 行,每行两个整数 x,y 表示 x,y 之间有一条边
第 n + 1 行给定一个整数 q 表示询问数(1 ⩽ q ⩽ 5 × 105)
接下来 q 行,每行两个整数 v(1 ⩽ v ⩽ n), k(1 ⩽ k ⩽ 107)与题目描述一致
输出格式
每行输出一个回答,如果小祥加入了 Mujica 输出“Yes”,否则输出”No”(不含引号)。
Page 16 of 24
CUSTACM May Contest 2025 年/5 月/17 日
样例
standard input standard output
8
1 2
1 3
1 5
2 4
3 6
6 7
7 8
8
1 4
2 7
3 5
4 2
5 6
6 1
7 6
8 2
Yes
Yes
Yes
No
Yes
No
Yes
No
#include <iostream>
#include <cstring>
#include <queue>
using namespace std;const int N = 2e5 + 10; // 最大节点数
const int M = 4e5 + 10; // 最大边数(无向边要存两次)// 链式前向星存图
int h[N]; // h[a]表示节点a的第一条边的存储位置
int e[M]; // e[idx]存储第idx条边的终点
int ne[M]; // ne[idx]存储第idx条边的下一条边
int idx; // 边的计数器// 添加边(无向图要添加两次)
void add_edge(int a, int b) {e[idx] = b; // 记录边的终点ne[idx] = h[a]; // 新边的next指向原来的第一条边h[a] = idx++; // 更新节点a的第一条边
}// BFS函数
pair<int, vector<int>> bfs(int start, int n) {vector<int> dist(n + 1, -1); // 距离数组queue<int> q;dist[start] = 0;q.push(start);while (!q.empty()) {int u = q.front();q.pop();// 遍历u的所有邻接点for (int i = h[u]; i != -1; i = ne[i]) {int v = e[i];if (dist[v] == -1) {dist[v] = dist[u] + 1;q.push(v);}}}// 找到最远点int max_dist = -1, farthest = start;for (int i = 1; i <= n; ++i) {if (dist[i] > max_dist) {max_dist = dist[i];farthest = i;}}return {farthest, dist};
}int main() {ios::sync_with_stdio(false);cin.tie(nullptr);memset(h, -1, sizeof h); // 初始化邻接表int n;cin >> n;for (int i = 0; i < n - 1; ++i) {int a, b;cin >> a >> b;add_edge(a, b); // 无向图添加双向边add_edge(b, a);}// 第一次BFS找直径端点auto [u, _] = bfs(1, n);// 第二次BFS找另一个端点并记录距离auto [v, dist_u] = bfs(u, n);// 第三次BFS记录距离auto [w, dist_v] = bfs(v, n);int q;cin >> q;while (q--) {int x, k;cin >> x >> k;cout << (max(dist_u[x], dist_v[x]) <= k ? "Yes" : "No") << endl;}return 0;
}
-
dist
数组:记录每个点到起点的距离 -
max_element
:找出数组中的最大值(从dist[1]开始找,因为dist[0]没用) -
find
:找到这个最大值在数组中的位置 -
farthest
:就是离起点最远的那个点的编号 -
最后返回:最远点 + 所有点的距离数组