P5663

洛谷题目传送门

分析

可以发现求第 x x x 个工人生产 L L L 阶段的零件需不需要编号 1 1 1 的工人提供原材料,等同于问 1 1 1 x x x 之间有没有长度为 L L L 的路径。
而且我们很容易得出如果两点间有长度为偶数的路径,那么不一定有长度为奇数的路径,反过来同理,
所以我们可以分别维护长度为奇数和偶数的最短路径长度,此后对于每组询问:

  • 如果 L L L 为奇数,且 o d d x < = L odd_x <= L oddx<=L,则答案为 YES
  • 如果 L L L 为偶数,且 e v e n x < = L even_x <= L evenx<=L,则答案为 YES
  • 其余情况为 NO

注意

由于边权为1, BFS即可维护最短路,不能使⽤ v i s vis vis 数组判重,因为现在需要维
护奇数和偶数2种最短路,进出队列不⽌1次。

代码

#include 

using namespace std;

const int N = 1e5 + 5;
int n, m, q, vis[N], odd[N], even[N];
vector <int> nbr[N];//邻接表存边 

void bfs(){
	memset(odd, 0x3f, sizeof odd);//初始化 
	memset(even, 0x3f, sizeof even);
	queue < pair <int, int> > q;
	q.push(make_pair(1, 0));
	
	while(!q.empty()){
		int x = q.front().first, step = q.front().second;
		q.pop();
		for(int i = 0; i < nbr[x].size(); i ++){
			int nxt = nbr[x][i];
			if(step % 2 == 0){
				if(step + 1 < odd[nxt]){//更新到下一个点的最短奇数距离 
					odd[nxt] = step + 1;
					q.push(make_pair(nxt, step + 1));
				}
			}else{
				if(step + 1 < even[nxt]){//更新到下一个点的最短偶数距离 
					even[nxt] = step + 1;
					q.push(make_pair(nxt, step + 1));
				}
			}
		} 
	} 
}

int main(){
	cin >> n >> m >> q;
	for(int i = 1; i <= m; i ++){
		int u, v;
		cin >> u >> v;
		nbr[u].push_back(v);//添加双向边 
		nbr[v].push_back(u); 
	}
	bfs();
	for(int i = 1; i <= q; i ++){
		int a, L;
		cin >> a >> L;
		if(L % 2 == 0){//长度为奇数 
			if(even[a] > L){
				cout << "No\n";
			}else{
				cout << "Yes\n";
			}
		}else{//长度为偶数 
			if(odd[a] > L){
				cout << "No\n";
			}else{
				cout << "Yes\n";
			}
		}
	}
	return 0;
}

你可能感兴趣的:(算法,宽度优先,c++,数据结构)