以1为原点
让每个点i的dist[i]经过偶数条边到i的最短路(每条边权值为1)
dist[i+n]代表经过奇数条边到i的最短路
因为一条双向边可以用2的耗费重复走,
所以每张工单只需要判断一下l是奇是偶,
再判断一下a对应的域的最短路是否比l短就可以。
C++ 代码
代码有点长,需要耐心才能看完
#include<iostream>
#include<queue>
#include<cstring>
using namespace std;
typedef pair<int,int> PII;
const int N=200005,M=400005;
int idx=1,h[N],t[M],ne[M],dist[N],n,m,q;
int st[N];
priority_queue<PII,vector<PII>,greater<PII>> que; //dijkstra堆优化那个优先队列
void add(int x,int y){ //加边函数
t[idx]=y,ne[idx]=h[x],h[x]=idx++;
}
void dijkstra(){ //堆优化的dijkstra
memset(dist,0x3f,sizeof dist);
dist[1]=0;
que.push({0,1});
while(que.size()){
PII now=que.top();
que.pop();
if(st[now.second])
continue;
st[now.second]=1;
for(int i=h[now.second];i;i=ne[i])
if(dist[t[i]]>now.first+1){
dist[t[i]]=now.first+1;
que.push({dist[t[i]],t[i]});
}
}
}
int main(){
scanf("%d%d%d",&n,&m,&q);
while(m--){
int x,y;
scanf("%d%d",&x,&y);
add(x,n+y),add(n+x,y),add(y,n+x),add(n+y,x); //走一步一定会从奇变偶或从偶变奇
}
dijkstra();
while(q--){
int a,l;
scanf("%d%d",&a,&l);
if(!h[1]) //这里是个坑,如果1节点没有任何传送带,那么任何工单都是No
puts("No");
else if(l%2)
puts(dist[a+n]<=l?"Yes":"No");
else
puts(dist[a]<=l?"Yes":"No");
}
return 0;
}