普及组第四题广搜详解
算法分析:本题使用广搜,意在的第一次就找到1点和某点的最短路。
思路:1、当1节点 到某点奇数最短路径小于等于完成的阶段(奇数),肯定要提供原材料2、当1节点 到某点偶数最短路径小于等于完成的阶段(偶数),肯定要提供原材料
注意这道题不要使用最短路径算法,因为各边无边权值。
本题分为3部分,这里是第一部分
1.输入
#include <bits/stdc++.h>
using namespace std;
struct node {
int u, step;
};
node tmp;
queue<node> q;
vector<int> G[100007];
int vis[100007], dis[100007][2], u, v, n, m, qu, a, l, step, rua;
int main() {
cin >> n >> m >> qu;
for (int i = 1; i <= m; i++) {
cin >> u >> v;
G[u].push_back(v);
G[v].push_back(u);
}
讲解1:
1.定义结构体方便队列可以储存两个数。(u–点,step–到此点的最短路。)
2.vis[ ]用来标记这个点是否被用过。
2.bfs广搜 主体部分
memset(dis, 0x3f, sizeof(dis));
tmp.u = 1;//1点到1点
tmp.step = 0;//距离为0
q.push(tmp);//入队
if (G[1].size() > 0) {
dis[1][0] = 0;
vis[1] = 1;
}
while (!q.empty()) {
step = q.front().step + 1;
rua = step % 2;
for (int i = 0; i < G[q.front().u].size(); i++) {
v = G[q.front().u][i];
if (!vis[v]) { //广搜第一次找到点v,一定是最短路。
dis[v][rua] = step;
tmp.u = v;
tmp.step = step;
q.push(tmp);
vis[v] = 1;
} else {
if (step < dis[v][rua]) {
dis[v][rua] = step;
tmp.u = v;
tmp.step = step;
q.push(tmp);
}
}
}
q.pop();
}
讲解2:
1.二维数组可以用memset来初始化。
2.dis[ ][ ]用来存放到dis[到某点][奇或偶]
3.While外的if判断是用来判断1节点有没有和任何节点相连。
4.“+1”操作代表的是搜索下一个相邻的点,rua看奇偶。
5.for循环用来看与下一个节点相连的点和哪些点相连,v取出相邻的点。
6.如果v点第一次找到(到其距离最短)。那么就将1到v的距离入队。
7.入队后标记此点已被搜索。
8.else:如果找到另一条最短路(奇偶一共两条),那么正常更新 。
9.把这个点找完之后,让他出队。
3.最后的输入输出
for (int i = 1; i <= qu; i++) {
cin >> a >> l;
if (l >= dis[a][l % 2])
cout << "Yes" << endl;
else
cout << "No" << endl;
}
return 0;
}
讲解3
这里就不过多说了。a编号为a的工人l为第l阶段…