abc 254 e 题解
abc 254 e
题意
给定一个 \(n\) 个点 \(m\) 条边的简单无向图,点分别编号为 \(1, 2, \dots, n\),第 \(i\) 条边连接 \(a_i\) 和 \(b_i\)。每个点的度数至多为 \(3\)。
对于 \(i = 1, 2, \dots, q\),请你求出距离点 \(x_i\) 距离不超过 \(k_i\) 的点的编号之和。
\(1 \le n \le 1.5 \times 10 ^ 5\)。
\(0 \le m \le \min(\frac{n(n - 1)}{2}, \frac{3n}{2})\)。
\(1 \le a_i, b_i \le n\)。
\(1 \le q \le 1.5 \times 10 ^ 5\)。
\(1 \le x_i \le n\)。
\(1 \le k_i \le 3\)。
思路
dfs 或者 bfs(搜索)。
题目有两个很明显的提示:每个点的度数至多为 \(3\) 和 \(1 \le k_i \le 3\)。
这就说明,每次最多找到 \(3 ^ 3\) 个点。
直接搜索即可。
注意
因为是图,所以需要标记每个点是否被走到过,因为每次清空标记数组过于浪费时间,所以可以用一个额外的数组记录最后一次更新最短路是在第几次询问。
时间复杂度为 \(O(q \times 3 ^ 3)\)。
#include <bits/stdc++.h>
using namespace std;
const int N = 1.5e5 + 10;
int n, m, q, x, k, mmax[N], d[N];
vector<int> g[N];
long long Solve(int x, int k, int id) {
long long ans = x;
queue<int> que;
que.push(x), mmax[x] = id, d[x] = 0; // 初始状态
while (!que.empty()) {
int u = que.front();
que.pop();
if (d[u] >= k) { // 如果最短路超过 k[i]
break;
}
for (int v : g[u]) {
if (mmax[v] < id) {
mmax[v] = id, que.push(v), ans += v, d[v] = d[u] + 1; //入队
}
}
}
return ans;
}
int main() {
ios::sync_with_stdio(0), cin.tie(0);
cin >> n >> m;
while (m--) {
int a, b;
cin >> a >> b;
g[a].push_back(b), g[b].push_back(a);
}
cin >> q;
for (int i = 1; i <= q; i++) {
cin >> x >> k;
cout << Solve(x, k, i) << '\n';
}
return 0;
}