Files
python/TangDou/CSP-J/J2_2019/4_2.cpp
HuangHai 1f397eca87 'commit'
2025-08-30 18:35:01 +08:00

83 lines
2.9 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include <bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
#define x first // 节点号
#define y second // 奇偶性
const int N = 100010, M = 200010;
int n, m, Q;
int h[N], e[M], ne[M], idx;
void add(int a, int b) {
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
int dist[N][2]; // 奇偶最短路 dist[5][0]:4,dist[6][1]:3
queue<PII> q;
// ① 因边边权都是1,不需要Dijkstra或者Floyd,只需要bfs即可
// ② 由于本题是强调 奇偶性 ,所以,需要使用 拆点 的思想
// ③ 所谓拆点,就是像状态机或者DP中扩展维度的思想,将奇偶点分开,把混沌的事情清晰化。
// dist[i][0]:表示是偶数步的点,值是最小步数
// dist[i][1]:表示是奇数步的点
void bfs() {
memset(dist, 0x3f, sizeof dist); // 预求最短,先设最大
dist[1][0] = 0; // 1是起点,0:理解为从1号出发,到1号结束,走了0步的结果,所以是偶数步,步数为0
q.push({1, 0}); // 起点入队列
while (q.size()) {
auto u = q.front();
q.pop();
for (int i = h[u.x]; ~i; i = ne[i]) { // u点
PII v = {e[i], u.y ^ 1}; // 0 ^ 1 = 1 1 ^ 1 =0
if (dist[v.x][v.y] > dist[u.x][u.y] + 1) { // 如果利用u可以更新v这个点
dist[v.x][v.y] = dist[u.x][u.y] + 1; // 更新
q.push(v); // v的最短距离更新了,入队列,去更新更多的点
}
}
}
}
int main() {
// 加快读入
ios::sync_with_stdio(false), cin.tie(0);
memset(h, -1, sizeof h);
cin >> n >> m >> Q;
while (m--) {
int a, b;
cin >> a >> b;
add(a, b), add(b, a);
}
bfs();
while (Q--) {
int a, l;
cin >> a >> l;
/*
如果不写下面的特判,会被欺负死:
3 1 1
2 3
1 2
第一行三个正整数 n,m 和 q,分别表示工人的数目、传送带的数目和工单的数目。
也就是3个工人,1个传送带,1个工单
传送带是2~3,也就是1是与世隔绝的
接下来 q 行,每行两个正整数 a 和 L,表示编号为 a 的工人想生产一个第 L 阶段的零件。
1号工人,想生产2阶段的零件
由于1号工人是与世隔绝的,没有人给它提供1阶段的零件,肯定返回No,此时需要特判,返回答案
*/
if (h[1] == -1)
puts("No");
else if (l >= dist[a][l & 1]) // l是奇数,并且大于奇数最短路,则可以通过+2,+4,+6...等方法来回磨,凑够l就完事
// l是偶数,并且大于偶数最短路,则可以通过+2,+4,+6...等方法来回磨,凑够l就完事
puts("Yes");
else
puts("No");
}
return 0;
}