洛谷P5663题解

原题链接:https://www.luogu.com.cn/problem/P5663

更好的使用方式:https://www.luogu.com.cn/article/0o6pvn64

警告:严禁抄袭

分析

此题是一道图论的题目,可以将每个工人看成一个点,将双向的零件传送带看作无向边。

只管的做法是按照题目的描述规则,使用递归直接模拟,这样可以通过前 88 个测试点,得到 4040 分。对于满分做法,需要观察这个无向图本身的性质,容易发现 xx 号点生产一个 LL 阶段零件时,如果能找到一条从 xx 号点到 11 号点提供原材料。

通过样例 22 的情况,我们发现 33 号点到 11 号点有两条简单的路径,3213\to2\to134513\to4\to5\to1。那么,如果 33 号点想生产第一阶段的零件,因为两条简单路径的最短长度是 22,因此至少要生产第 22 阶段的零件才能到达 11 号点。此外,所有大于 22 的偶数阶段也都是需要 11 号点给材料的,因此会有 321213\to2\to1\cdots\to2\to1 这样的方式使得 11 号点提供原材料,因为可以通过 3451513\to4\to5\to1\cdots\to5\to1 的方式到达一号点。

由此可得,只需预处理出 11 号点到其他所有点的最短奇数路径和最短偶数路径的长度。当 xx 号点生产一个 LL 阶段的零件时,如果 LL 是奇数且 LL 大于等于 xx 号点到 11 号点的最短奇数路径长度,就需要 11 号点生产原材料。如果 LL 是偶数且 LL 大于等于 xx 号点到 11 号点的最短偶数路径长度,就需要 11 号点生产原材料。

AC 代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
#include<bits/stdc++.h>
using namespace std;
int n, m, Q;
//g[i] 存储所有与i相连的点
vector<int> g[100005];
//odd[i]:从1到i的最短奇数路径的长度
//even[i]:从1到i的最短偶数数路径的长度
int odd[100005], even[100005];
queue<int> q;
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin >> n >> m >> Q;
for(int i = 1;i <= m;i++){
int u, v;
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
memset(odd, 0x3f, sizeof(odd));
memset(even, 0x3f, sizeof(even));
even[1] = 0;
q.push(1);
while(!q.empty()){
int u = q.front();
q.pop();
for(int i = 0;i < g[u].size();i++){
int v = g[u][i];
//u->i
bool flag = false;// 是否有优化
if(odd[u] + 1 < even[v]){
even[v] = odd[u] + 1;
flag = true;
}
if(even[u] + 1 < odd[v]){
odd[v] = even[u] + 1;
flag = true;
}
if(flag)
q.push(v);
}
}
for(int i = 1;i <= Q;i++){
int a, L;
cin >> a >> L;
if(L % 2 == 0 && even[a] <= L)
cout << "Yes" << endl;
else if(L % 2 == 1 && odd[a] <= L)
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}

AC 记录:https://www.luogu.com.cn/record/197005888


洛谷P5663题解
https://lijingshu2014.github.io/2025/10/03/洛谷P5663题解/
作者
lijingshu
发布于
2025年10月3日
许可协议