传送门:P5663 [CSP-J2019] 加工零件
这是一篇写于 2024.8.17 的做题记录,祝稻米朋友们节日快乐。
废话还是少说一点比较好qwq
题目意思:(一个很抽象的东西)
说白了其实就是给你一张无向图,然后有 p 次询问,每次询问给你一个 v 和 L ,问你从 1 号点到 v 号点 有没有 长度为 L 的边。
注意:
- 每条边是可以重复走的
- 这是一张无向图
- 可能会有孤点的情况
思路:
自信满满的开题 qwq
然鹅。。。
不会啊!!!!
瞬间开启自我怀疑状态
翻了翻题解,判断奇偶是什么东西???
于是。。。
思考ing。。。。
终于!
如果 L 与 从点 1 出发到达该点的路径长度 奇偶性一致
换句话说就是:
如果 L 是奇数,并且从 1 号点出发有一条能到达该点的 路径长度为奇数,路径长度 <= L 的边
那么他就需要提供原材料,因为该材料在加工过程中能在相邻两个工人之间来回横跳
偶数情况亦然
所以我们只需要求 1 到所有点的奇数路径 和 偶数路径
看是否有与 L 奇偶性相同的边,且长度<=L
为了保证长度<=L,我们求 1到所有点的奇数最短路 和 偶数最短路
思路明确了就很好写了 QaQ
最终代码:
就跑一个最短路啦
SPFA,启动!
#include<bits/stdc++.h>
using namespace std;
const int maxn=100100;
const int maxm=100100;
int m,n,qq;
int en=0;
int fir[maxn];
struct edge{
int v;
int next;
}ed[maxm*2];
void add_edge(int u,int v)
{
en++;
ed[en].v=v;
ed[en].next=fir[u];
fir[u]=en;
}
int jdist[maxn],odist[maxn];
bool inque[maxn];
queue<int> q;
void spfa(int r)
{
memset(jdist,0x3f3f3f,sizeof(jdist));
memset(odist,0x3f3f3f,sizeof(odist));
odist[r]=0;
q.push(r);
inque[r]=true;
while(!q.empty())
{
int now=q.front();
q.pop();
inque[now]=false;
for(int i=fir[now];i;i=ed[i].next)
{
int v=ed[i].v;
if(odist[v]>jdist[now]+1||jdist[v]>odist[now]+1){
jdist[v]=min(jdist[v],odist[now]+1);
odist[v]=min(odist[v],jdist[now]+1);
if(!inque[v])
{
q.push(v);
inque[v]=true;
}
}
}
}
}
int main()
{
cin>>n>>m>>qq;
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
add_edge(u,v);
add_edge(v,u);
}
spfa(1);
while(qq--)
{
int v,l;
cin>>v>>l;
if(l%2==1&&jdist[v]<=l)cout<<"Yes"<<endl;
else if(l%2==0&&odist[v]<=l)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
return 0;
}
后记
- 因为用的是 SPFA ,孤点的情况对代码运行结果就没有影响了 qwq
- 这个题目保证了同一个点不会入队两次,
inque数组其实没用。。时间复杂度为 O(n+q) - 最后,对于边权为 1 的图来跑最短路,bfs 的方法也是可行的,复杂度与 spfa 一致