练习题T1
题目描述
凯凯的工厂正在有条不紊地生产一种神奇的零件,神奇的零件的生产过程自然也很神奇。工厂里有 n 位工人,工人们从 1∼n 编号。某些工人之间存在双向的零件传送带。保证每两名工人之间最多只存在一条传送带。
如果 x 号工人想生产一个被加工到第 L(L>1) 阶段的零件,则所有与 x 号工人有传送带直接相连的工人,都需要生产一个被加工到第 L−1 阶段的零件(但 x 号工人自己无需生产第 L−1 阶段的零件)。
如果 x 号工人想生产一个被加工到第 1 阶段的零件,则所有与 x 号工人有传送带直接相连的工人,都需要为 x 号工人提供一个原材料。
轩轩是 1 号工人。现在给出 q 张工单,第 i 张工单表示编号为 ai 的工人想生产一个第 Li 阶段的零件。轩轩想知道对于每张工单,他是否需要给别人提供原材料。他知道聪明的你一定可以帮他计算出来!
输入格式
第一行三个正整数 n,m 和 q,分别表示工人的数目、传送带的数目和工单的数目。
接下来 m 行,每行两个正整数 u 和 v,表示编号为 u 和 v 的工人之间存在一条零件传输带。保证 u=v。
接下来 q 行,每行两个正整数 a 和 L,表示编号为 a 的工人想生产一个第 L 阶段的零件。
输出格式
共 q 行,每行一个字符串 Yes 或者 No。如果按照第 i 张工单生产,需要编号为 1 的轩轩提供原材料,则在第 i 行输出 Yes;否则在第 i 行输出 No。注意输出不含引号。
思路:最短路
转化条件
不难发现,需要 1 号节点提供第 L 阶段零件原材料的充要条件是“能通过走 L 步到达 1 号节点”。
并且,只需要考虑一个节点的情况(单源)。
所以使用广搜~~(面搜)~~寻找最短路。
奇偶?
由于存在双向传送带,所以这个图没有方向性。
可以花费两步走一次来回,即:走 k 步可以到达 ⇒ 走 k+2 步可以到达。
因此,只需要分别考虑奇数步的最短路和偶数步的最短路即可。
实现
使用 oddmin[i],evenmin[i] 代表 1→i 奇偶步数的最短路。
若 i 与 j 相连,则:
1 2
| odd_min[j] = even_min[i] + 1; even_min[j] = odd_min[i] + 1;
|
同时,在搜索的时候不能仅使用一个 vis 记录访问状态,因为这样只能求出一种情况的最短路。
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <bits/stdc++.h>
using namespace std; using ll = long long;
inline void minset(int &t, int other) { t = min(t, other); }
inline void maxset(int &t, int other) { t = max(t, other); }
const int inf = 0x7f7f7f7f;
const int N = 1e5 + 10; const int M = 1e5 + 10;
int odd_min[N], even_min[N]; bool odd_vis[N], even_vis[N];
struct edge { int to, next; } edges[M];
struct node { int from, to; };
int head[N]; int pt = 1; string res[] = {"No", "Yes"};
int n, m, q;
void add_edge(int from, int to) { edge &e = edges[pt]; e.to = to; e.next = head[from]; head[from] = pt; pt++; }
void bfs() { int p = 1; even_min[1] = 0; even_vis[1] = true; queue<node> q; for(int i = head[1]; i; i = edges[i].next) { int from = 1, to = edges[i].to; q.push({from, to}); } while(q.size()) { node n = q.front(); q.pop(); bool flag = false; if(!odd_vis[n.to] && even_min[n.from] != inf) { odd_min[n.to] = even_min[n.from] + 1; odd_vis[n.to] = true; flag = true; } if(!even_vis[n.to] && odd_min[n.from] != inf) { even_min[n.to] = odd_min[n.from] + 1; even_vis[n.to] = true; flag = true; } if(flag) { for(int i = head[n.to]; i; i = edges[i].next) { int from = n.to, to = edges[i].to; q.push({from, to}); } } } }
int main() { cin >> n >> m >> q; int t1, t2; for(int i = 1; i <= m; i++) { cin >> t1 >> t2; add_edge(t1, t2); add_edge(t2, t1); } memset(odd_min, inf, sizeof odd_min); memset(even_min, inf, sizeof even_min); bfs(); for(int i = 0; i < q; i++) { cin >> t1 >> t2; if(t2 & 1) { cout << res[odd_min[t1] <= t2] << endl; } else { cout << res[even_min[t1] <= t2] << endl; } } return 0; }
|
什么情况?
无向图的数组长度应该为边数的二倍,edges[M]这里写小了。
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 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
| #include <bits/stdc++.h>
using namespace std; using ll = long long;
inline void minset(int &t, int other) { t = min(t, other); }
inline void maxset(int &t, int other) { t = max(t, other); }
const int inf = 0x7f7f7f7f;
const int N = 1e5 + 10; const int M = 1e5 + 10;
int odd_min[N], even_min[N]; bool odd_vis[N], even_vis[N];
struct edge { int to, next; } edges[2 * M];
struct node { int from, to; };
int head[N]; int pt = 1; string res[] = {"No", "Yes"};
int n, m, q;
void add_edge(int from, int to) { edge &e = edges[pt]; e.to = to; e.next = head[from]; head[from] = pt; pt++; }
void bfs() { int p = 1; even_min[1] = 0; even_vis[1] = true; queue<node> q; for(int i = head[1]; i; i = edges[i].next) { int from = 1, to = edges[i].to; q.push({from, to}); } while(q.size()) { node n = q.front(); q.pop(); bool flag = false; if(!odd_vis[n.to] && even_min[n.from] != inf) { odd_min[n.to] = even_min[n.from] + 1; odd_vis[n.to] = true; flag = true; } if(!even_vis[n.to] && odd_min[n.from] != inf) { even_min[n.to] = odd_min[n.from] + 1; even_vis[n.to] = true; flag = true; } if(flag) { for(int i = head[n.to]; i; i = edges[i].next) { int from = n.to, to = edges[i].to; q.push({from, to}); } } } }
int main() { cin >> n >> m >> q; int t1, t2; for(int i = 1; i <= m; i++) { cin >> t1 >> t2; add_edge(t1, t2); add_edge(t2, t1); } memset(odd_min, inf, sizeof odd_min); memset(even_min, inf, sizeof even_min); bfs(); for(int i = 0; i < q; i++) { cin >> t1 >> t2; if(t2 & 1) { cout << res[odd_min[t1] <= t2] << endl; } else { cout << res[even_min[t1] <= t2] << endl; } } return 0; }
|