CSP历年复赛题-P5663 [CSP-J2019] 加工零件
原题链接:https://www.luogu.com.cn/problem/P5663
题意解读:工人是图中的点,传送带是图中的无向边,给出q个询问a, l,判断是否能有一条1号点到a点的路径为l。
解题思路:
考试的关键是拿分!同样可以来面向数据编程:
1、测试点 1∼4,1≤𝑛,𝑚≤1000,𝐿=1
由于L=1,距离1号点路径为1,说明存在1号点到询问点之间的边,直接通过邻接矩阵即可判断
20分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 1005, M = 1005;
int n, m, q;
int g[N][N];
int main()
{
cin >> n >> m >> q;
int u, v;
for(int i = 1; i <= m; i++)
{
cin >> u >> v;
g[u][v] = g[v][u] = 1;
}
int a, l;
while(q--)
{
cin >> a >> l;
if(g[1][a] == 1) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}
2、测试点 5∼8,,
#include <bits/stdc++.h>
using namespace std;
const int N = 1005, M = 1005;
int n, m, q;
vector<int> g[N];
bool d[N][15]; //d[i][j]=true表示从1号点到i点有一条路径距离为j
void dfs(int u, int dist)
{
if(dist > 10) return;
if(d[u][dist]) return;
d[u][dist] = true;
for(int v : g[u])
{
dfs(v, dist + 1);
}
}
int main()
{
cin >> n >> m >> q;
int u, v;
for(int i = 1; i <= m; i++)
{
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
dfs(1, 0);
int a, l;
while(q--)
{
cin >> a >> l;
if(d[a][l]) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}
3、其余数据
由于此题是求从1点到其他点可能的所有路径长度,普通的最短路如果通过bfs某个点不会重复走,但此题不一定是求最短路,可能是经过了一圈之后又回到某个点。
进一步分析,假设从1点到a的最短路径是l,那么必然可以存在从a点经过一个相邻点往返一次回到a点的路径l+2,
同理到a点的路径还有l+4,l+6,l+8,l+10....,也就是说与从1到a的最短路同奇偶性的路径都能到达
那么,就只需要计算从1到a的最短路,有两种:奇数的最短路、偶数的最短路,其余的都不需要计算
定一个数据变量保存每个点到1的距离:dist[N][2],dist[i][0]表示1到i点的偶数最短路,dist[i][1]表示1到i点的奇数最短路
通过bfs计算最短路,通过dist来更新距离同时用作已走过的标记
对于q个询问a,l,判断l的奇偶性,再看a的奇或者偶最短路是否小于等于l。
100分代码:
#include <bits/stdc++.h>
using namespace std;
const int N = 100005;
int n, m, q;
vector<int> g[N];
int dist[N][2];
struct node
{
int id; //节点编号
int distance; //距离1号点距离
};
void bfs()
{
memset(dist, -1, sizeof(dist));
queue<node> q;
q.push({1, 0});
dist[1][0] = 0;
while(q.size())
{
node a = q.front();
q.pop();
for(int v : g[a.id])
{
if(dist[v][(a.distance + 1) % 2] == -1)
{
dist[v][(a.distance + 1) % 2] = a.distance + 1;
q.push({v, a.distance + 1});
}
}
}
}
int main()
{
cin >> n >> m >> q;
int u, v;
for(int i = 1; i <= m; i++)
{
cin >> u >> v;
g[u].push_back(v);
g[v].push_back(u);
}
bfs();
int a, l;
while(q--)
{
cin >> a >> l;
if(dist[a][l % 2] != -1 && l >= dist[a][l % 2]) cout << "Yes" << endl;
else cout << "No" << endl;
}
return 0;
}