CSP 2019 第四题: 加工零件

题目链接
题目:
在这里插入图片描述

知识点:
图、最短路径、bfs
思路:

  • 先都读懂题,题目的零件加工是需要相邻点的参与,除非不加工,否则相邻的一定会提供零件
  • 题目要求的是某个节点产某个阶段的零件,问第一个节点需不需要提供零件(原材料)。不难看出,这是和路径相关的题目,节点N 要生产第L阶段的零件需要节点1提供零件,那么N到第一个节点的路径至少为L-1,这是直观看出来的,但实际上,要使得该节点到第一个节点的路径最小,我们得求出最短路径,也就是BFS,当L比路径大时,在节点1和N之前肯定会多出2的倍数的路径(在两个节点之间可以多生产几个阶段),因此只要加工的阶段L==最短路径+2n即可,具体在哪些节点多生产几次可以不关心,当最短路径为奇数,+2n后依旧是奇数,反之则是偶数
  • 以第四个节点生产L5阶段为例子,路径为3,L5则是在第一阶段和第二阶段多生产一次即可。因此最短路径是奇数,L就必须要求是大于等于最短路径的奇数,反之,最短路径是偶数,则L必须是大于等于最短路径的偶数

在这里插入图片描述

数据约束:
数据无特别约束,bfs时间复杂度为O(n),无超时
代码参考:

  • 由于储存图的的数据关系时为了方便遍历用邻接矩阵,矩阵设为动态数组为了方便储存邻接关系,如果时静态二维数组就还得多遍历几次
  • 写完才发现代码有点冗长,处理就奇偶的最短路径时,数组可以用二维数组,a[1][]存偶,奇存a[][1],这样判断时直接用a[][y%2]即可,不用多些几个判断
  • 最短路径除了BFS还有 Dijkstra、SPFA等,但是对于无权值的最短路径,BFS也就足够用了
//建图,利用bfs找出最短的技术路径和偶数路径(也可以spfa和jst)
#include<bits/stdc++.h>
#define MAX_N 200005
using namespace std;
int n,m,l;
vector<int> v[MAX_N];
struct stu{
	int k,dis;//记录点和到该点的距离 
	stu(int x=0,int l=0) : k(x),dis(l){};//设置初始化 默认为0 
}; 
queue <stu> q; 
int even[MAX_N],odd[MAX_N];//分别储存奇偶路径 
void bfs();
int main(){
	cin>>n>>m>>l; //n个工人,m条数  ,l个数据 
	int x,y;
	for(int i=1;i<=m;i++){
		cin>>x>>y;
		v[x].push_back(y),v[y].push_back(x);  //邻接表储存结果 
	}
	
	bfs();
	for(int i=1;i<=l;i++){
		cin>>x>>y;  
		if(y%2==0){
			if(odd[x]<=y&&odd[x]!=-1){
				cout<<"Yes"<<endl;
			}else{
				cout<<"No"<<endl;
			} 
		}else{
			even[x]<=y&even[x]!=-1 ? cout<<"Yes"<<endl : 	cout<<"No"<<endl;
		}
			 	
	 } 
	return 0;
}
void bfs(){
	memset(odd,-1,sizeof(odd));
	memset(even,-1,sizeof(even));//每次进来初始化节点情况
	q.push(stu(1,0)); //第一个数据入队 
	while(!q.empty()){
	 	stu now = q.front();
	 	q.pop();
	 	int x = now.k;
	 	//vector数组长度也可以是 
	 	for(int p =0;p<(int) v[x].size();p++){ //遍历该行的邻接表(相邻节点) 
	 		int y= v[x][p];
	 		int  num = now.dis+1;
	 		//如果没被访问过就直接更新否则退出 
	 		if(num%2==0){//偶数 
	 			if(odd[y] != -1) continue;
	 			else odd[y] = num;
			 }else{
			 	if(even[y]!=-1) continue;
			 	else even[y] = num;
			 }
//			 cout<<"bfs:"<<y<<": "<<num<<endl;
			 q.push(stu(y,num));
		 }
	 }
	
} 
  • 3
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值