【题解】LuoGu5663:加工零件

原题传送门
传送带可以理解为边权为1的一条边
题目可以转化成一个可以重复来回走的无向图中,对于每个询问 ( a , L ) (a,L) (a,L),询问1是否有到 a a a长度为 L L L的路径

那么如果两个点之间存在长度为 x x x的路径,那么这两个点必定存在长度为 x + 2 x+2 x+2的路径
但是这两个点之间却不一定存在长度为 x − 2 x-2 x2,或是 x + 1 x+1 x+1的路径

所以我们可以求1到每个点的奇数最短路和偶数最短路,用dijkstra就好了

Code:

#include 
#define maxn 100010
using namespace std;
struct Edge{
	int to, next;
}edge[maxn << 1];
struct heap{
	int u, dis;
	bool operator < (const heap &x) const{ return x.dis < dis; }
};
priority_queue <heap> q;
int dis[maxn][2], vis[maxn][2], n, m, Q, num, head[maxn];

inline int read(){
	int s = 0, w = 1;
	char c = getchar();
	for (; !isdigit(c); c = getchar()) if (c == '-') w = -1;
	for (; isdigit(c); c = getchar()) s = (s << 1) + (s << 3) +(c ^ 48);
	return s *w;
}

void addedge(int x, int y){ edge[++num] = (Edge){y, head[x]}, head[x] = num; }

int main(){
	n = read(), m = read(), Q = read();
	for (int i = 1; i <= m; ++i){
		int x = read(), y = read();
		addedge(x, y), addedge(y, x);
	}
	for (int i = 2; i <= n; ++i) dis[i][0] = dis[i][1] = 2e9;
	dis[1][1] = 2e9;
	q.push((heap){1, 0});
	while (!q.empty()){
		heap tmp = q.top(); q.pop();
		int u = tmp.u, d = tmp.dis, now = d & 1, nxt = now ^ 1;
		if (vis[u][now]) continue; vis[u][now] = 1;
		for (int i = head[u]; i; i = edge[i].next){
			int v = edge[i].to;
			if (dis[v][nxt] > dis[u][now] + 1){
				dis[v][nxt] = dis[u][now] + 1;
				if (!vis[v][nxt]) q.push((heap){v, dis[v][nxt]});
			}
		}
	}
	while (Q--){
		int x = read(), y = read();
		if (y >= dis[x][y & 1]) puts("Yes"); else puts("No");
	}
	return 0;
}

你可能感兴趣的:(题解,noip,最短路,题解,LuoGu,NOIp,最短路)