CSP-J 2019 T4 加工零件 题解
CSP-J 2019 T4 加工零件 题解
前言
洛谷P5663 T4 加工零件(BFS,最短路)
题意
工厂里有 \(n\) 位工人,工人们从 \(1 \sim n\) 编号。某些工人之间存在双向的零件传送带。保证每两名工人之间最多只存在一条传送带。
如果 \(x\) 号工人想生产一个被加工到第 \(L\,(L \gt 1)\) 阶段的零件,则所有与 \(x\) 号工人有传送带直接相连的工人,都需要生产一个被加工到第 \(L - 1\) 阶段的零件(但 \(x\) 号工人自己无需生产第 \(L - 1\) 阶段的零件)。
如果 \(x\) 号工人想生产一个被加工到第 \(1\) 阶段的零件,则所有与 \(x\) 号工人有传送带直接相连的工人,都需要为 \(x\) 号工人提供一个原材料。
轩轩是 \(1\) 号工人。现在给出 \(q\) 张工单,第 \(i\) 张工单表示编号为 \(a_i\) 的工人想生产一个第 \(L_i\) 阶段的零件。轩轩想知道对于每张工单,他是否需要给别人提供原材料。
数据规模与约定
对于 \(100\%\) 的数据,保证 \(1 \le n,m,q \le 10^5,1 \le L \le 10^9\)。
题解
显而易见题目给的是无向图。
如果有一条 \(x \to y\) 的路径,长度为 \(dis\),那么一定存在长度为 \(dis + 2k(k \ne 0)\) 的路径(因为你可以在两个节点之间反复横跳)。
由于 \(dis\) 和 \(dis + 2k\) 的奇偶性相同,所以我们要求出从节点 \(1\) 到节点 \(a\) 的奇数长度最短路径和偶数长度最短路径,这个可以用 BFS,也可以 Dijkstra、SPFA……不过 BFS 最简单,所以我们写 BFS。
求出最短路径后,如果最短路径 \(\le L\),那么输出 Yes,否则输出 No。
特别注意:如果节点 \(a\) 和节点 \(1\) 不在一个连通块,那么肯定传播不到节点 \(1\),\(dis[a][L\&1]\) 就是 0x3F3F3F3F,记得特判。
Code
#include<bits/stdc++.h>
using namespace std;
/*====================*/
using lnt = long long;
/*====================*/
#define endl "\n"
/*====================*/
int n, m, q;
/*====================*/
const int N = 1e5 + 10;
/*====================*/
vector<int>adj[ N ];
/*====================*/
int dis[ N ][ 2 ];
//定义 dis(x, 0) 表示 x 节点到达 1 节点的最短「偶数长度」距离
//定义 dis(x, 1) 表示 x 节点到达 1 节点的最短「奇数长度」距离
/*====================*/
void BFS()
{
queue<int>que;
que.push(1);
dis[ 1 ][ 0 ] = 0;
while (!que.empty())
{
int u = que.front(); que.pop();
for (auto v : adj[ u ])
{
bool need = false;
if (dis[ v ][ 1 ] > dis[ u ][ 0 ] + 1)
{
dis[ v ][ 1 ] = dis[ u ][ 0 ] + 1;
need = true;
}
if (dis[ v ][ 0 ] > dis[ u ][ 1 ] + 1)
{
dis[ v ][ 0 ] = dis[ u ][ 1 ] + 1;
need = true;
}
if (need) que.push(v); //更新后才需要入队
}
}
}
/*====================*/
void Solve()
{
memset(dis, 0x3F, sizeof(dis));
cin >> n >> m >> q;
for (int i = 1; i <= m; i++)
{
int u, v; cin >> u >> v;
adj[ u ].push_back(v);
adj[ v ].push_back(u);
}
BFS();
for (int i = 1; i <= q; i++)
{
int num, lvl;
cin >> num >> lvl;
int dist = dis[ num ][ lvl & 1 ];
if (dist == 0x3F3F3F3F)
{
cout << "No" << endl;
continue;
}
if (dist <= lvl) cout << "Yes" << endl;
else cout << "No" << endl;
}
}
/*====================*/
int main()
{
freopen("work.in", "r", stdin);
freopen("work.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(nullptr), cout.tie(nullptr);
int T = 1; //cin >> T;
while (T--) Solve();
return 0;
}

浙公网安备 33010602011771号