【笔记】洛谷P5663 [CSP-J 2019] 加工零件(奇偶最短路)
题意
给出一张结点数为 n、边数为 m 的无向图。对于 q 个询问,输出所询问的顶点 a 与顶点 1 间,是否有一条长度为 L 的路径。
为什么询问的是顶点 a 与顶点 1 间,是否有一条长度为L的路径?
题目说“如果 x 号工人想生产一个被加工到第 L(L>1) 阶段的零件,则所有与 x 号工人有传送带直接相连的工人,都需要生产一个被加工到第 L−1 阶段的零件”,询问“ 1 号工人是否需要给别人提供原材料”。
当 L=1 时:
a 需要生产第一阶段零件 ⟺ a 的邻居需要提供原材料,1 需要给 a 提供原材料 ⟺ 1 是 a 的邻居
∴ 如果 1 要给 a 提供原材料,则 1 和 a 间必然存在长度为 1 的路径
当 L=2 时:
a 需要生产第二阶段零件 ⟺ a 的邻居需要生产第一阶段零件 ⟺ a 的邻居的邻居需要提供原材料,1 需要给 a 提供原材料 ⟺ 1 是 a 的邻居的邻居
∴ 如果 1 要给 a 提供原材料,则 1 和 a 间必然存在长度为 2 的路径
不难发现,当 L=x(x≥1) 时:
a 需要生产第 x 阶段零件
∴ 如果 1 要给 a 提供原材料,则 1 与 a 间必然存在长度为 x 的路径
题目即求 1 与 a 间是否存在长度为 L 的路径。
思路
根据朴素的常识,在相邻的两个顶点上来回移动的话,可以为当前路径增加偶数长度。如下图,1 至 3 的路径长度可以是 2(1→2→3)、4(1→2→1→2→3)、6(1→2→1→2→1→2→3)……

可以把 L 理解为从 a 走到 1 的步数,即使奇偶相同,只要步数不够多也无法到达,所以若计算出 1 和 a 最短路径长度为奇数 x,则当 L 恰为大于等于 x 的奇数时,1 需要给 a 提供原材料;同理,若计算出 1 和 a 最短路径长度为偶数 x,则当 L 恰为大于等于 x 的偶数时,1 需要给 a 提供原材料。算法思路如下。
- 计算每个顶点到 1 的奇偶最短路
- 如果 L 是奇数,则检查 a 到 1 的奇最短路是否小于等于 L;偶数同理
- 根据检查结果输出
代码
#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
int n,m,q;
int ji[100005],ou[100005]; // ji[i]=从顶点 i 到顶点 1 的奇数最短路,ou 同理
queue<pair<int,int> > que; // BFS用的队列;另外“>>”间要加空格,不然可能被解析为右移运算符
int main(){
scanf("%d%d%d",&n,&m,&q);
vector<vector<int> > a(n+1); // 邻接表,用矩阵内存会炸
int u,v;
for(int i=0;i<m;i++){
scanf("%d%d",&u,&v);
a[u].push_back(v);
a[v].push_back(u);
}
memset(ji,0x3f,sizeof(ji)); // 初始化为最大值,表示无法到达
memset(ou,0x3f,sizeof(ou));
que.push(make_pair(1,0)); // (编号,步数)
ou[1]=0; // BFS 起点为顶点 1
while(!que.empty()){ // BFS,求 1 到每个点的奇偶最短路
int cura=que.front().first;
int bu=que.front().second;
que.pop();
for(int i=0;i<a[cura].size();i++){
if(bu%2==0){
if(ji[a[cura][i]]>bu+1){
ji[a[cura][i]]=bu+1;
que.push(make_pair(a[cura][i],bu+1));
}
}
else{
if(ou[a[cura][i]]>bu+1){
ou[a[cura][i]]=bu+1;
que.push(make_pair(a[cura][i],bu+1));
}
}
}
}
// 按照所走步数奇偶判断可否到达
int cura,l;
while(q--){
scanf("%d%d",&cura,&l);
if(l%2==0){
if(ou[cura]<=l) printf("Yes\n");
else printf("No\n");
}
else{
if(ji[cura]<=l) printf("Yes\n");
else printf("No\n");
}
}
return 0;
}

浙公网安备 33010602011771号