加工零件:https://www.luogu.com.cn/problem/P5663
一下解释部分借鉴 fdszlzldalao
观察发现,由于1->2的路径长度为1,只要点2的阶段为奇数,则点1一定要提供原材料(1->2->1->2->...)
观察发现,由于1->2->3的路径长度为2,只要点3的阶段为偶数,则点1一定要提供原材料
从1到v,路径很多,长度不尽相同。如果1到v的路径长度存在4时,v在阶段4、6、8、10…时,1肯定可以为0。当v的路径长度存在3时,v在3、5、7、9…阶段,1肯定可以为0。
因此要求的就是1到v的最短奇数路径和最短偶数路径。
若v的阶段为偶数x,存在v的最短偶数路径y,满足x>=y,1即可为0。
若v的阶段为奇数x,存在v的最短奇数路径y,满足x>=y,1即可为0。
设dis[v][0]为1到v的最短偶数路径,设dis[v][1]为1到v的最短奇数路径,
则有:
dis[v][0] = min(dis[v][0],dis[u][1]+1)
dis[v][1] = min(dis[v][1],dis[u][0]+1)
对于初始点1,dis[1][0]显然等于0,dis[1][1]显然不可能,设为无穷大。
#include <bits/stdc++.h> using namespace std; const int maxn=200009; int head[maxn],dis[maxn][2],n,m,cnt=1,vis[100009],s,l,r; struct p{ int x,num; bool operator < (const p&tmp) const{ return x>tmp.x; } }; priority_queue<p>q; struct node{ int to,nxt,w; }d[maxn]; void add(int u,int v,int w){ d[cnt].to=v,d[cnt].w=w, d[cnt].nxt=head[u],head[u]=cnt++; } void ji(int z,int k){ p t;t.num=k,t.x=z; if(z%2==1&&dis[k][1]>z) { dis[k][1]=z; q.push(t); } if(z%2==0&&dis[k][0]>z) { dis[k][0]=z; q.push(t); } } void dij() { memset(dis,20,sizeof(dis)); dis[1][0]=0;p init;//起始偶数为0 init.num=1,init.x=0;q.push(init); while(!q.empty()) { p ans=q.top();q.pop(); if(vis[ans.num]) continue; vis[ans.num]=0; for(int i=head[ans.num];i;i=d[i].nxt) { int z=dis[ans.num][0]+d[i].w; ji(z,d[i].to); z=dis[ans.num][1]+d[i].w; ji(z,d[i].to); } } } int main() { cin>>n>>m>>s; for(int i=1;i<=m;i++) { cin>>l>>r; add(l,r,1);add(r,l,1); } dij(); for(int i=1;i<=s;i++) { cin>>l>>r; if(r%2==1&&dis[l][1]<=r) cout<<"Yes"; else if(r%2==0&&dis[l][0]<=r) cout<<"Yes"; else cout<<"No"; cout<<endl; } return 0; }