题目
P5663 [CSP-J2019] 加工零件 - 洛谷 https://www.luogu.com.cn/problem/P5663



思路
1.(n工人数量,m传送带数量,q询问次数)<=10^5
时间复杂度不能过O(q).
q次循环,每次直接判断
2.根据传送带连接工位,建立图
二维表需要nn=105*105=10^104字节>256M,超限
用邻接表
3.1号工位要提供原材料,所以就是第0阶段工位
宽搜(按距离递增顺序访问各节点,能天然保证首次访问节点时的距离是最短距离。)
计算每个工位到1号工位的最短距离
4.询问x阶段工位需不需要1号位提高原料,
首先工序号(其实就是步数)要大于等于该工位到1号位的距离
而且步数的奇偶性要同该距离一致
图,有n*n条路,只需记住最短的奇偶距离就行
5.注意:!(x%2)判断偶数,!x%2先算!。
6.时间复杂度O(q)
代码
#include <bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int n,//n个工人
m,//m个传送带
qm,//查询次数
a,//哪个工人
x,x2,//第一次连接的工人,第二次工人工序
even[N],//工人到1号工序的距离是偶数
odd[N];//工人到1号工序的传送带数是奇数
/*
bool link[N][N];1e5*1e5=1e10*4字节约等于40g,大于256M
*/
vector<int> v[N];//邻接表存储图,每个工人连接哪些工人
queue<int> q;//宽搜队列
void view(){
for(int i=1;i<=n;i++)cout<<i<<"\t偶:"<<even[i]<<"\t奇:"<<odd[i]<<endl;
}
int main(){
//freopen("data.cpp","r",stdin);
cin>>n>>m>>qm;
for(int i=1;i<=m;i++){//建立图,邻接表
cin>>a>>x;
v[a].push_back(x);
v[x].push_back(a);
}
q.push(1);//从1号工序出发,计算所有工序到1号的距离(步数)
even[1]=0;//问的是1号工人是否提供原材料,就是各工序到这里是0
/*0、2、4、6、8步数是偶数,even
1、3、5、7、9步数是奇数odd,跟工号无关,跟到1号的步数和本身的工序(哪个阶段)有关
如x工号在做第9工序,同1号的距离是奇数3,分别是x-y-z-0
9-8-7-6-5-4-3-2-1-0
x-y-z-0-z-0-z-0-z-0
1工号需要给x提供原料*/
while(!q.empty()){//宽搜
x=q.front();q.pop();//队首,始发工号
for(int i=0;i<v[x].size();i++){//遍历链接的所有工号
x2=v[x][i];//到达工号
if((x==1||even[x])&&!odd[x2]){//even[1]==0,所以用x==1补充
odd[x2]=even[x]+1;q.push(x2);
}
//到x工号是0偶数距离,则x到达x2是奇数距离
if(odd[x]&&!even[x2]&&x2!=1){//确保第一次访问x2
even[x2]=odd[x]+1;q.push(x2);
}
}
}
//view();
while(qm--){
cin>>a>>x;
//工序号大于等于到达1号的步数(宽搜最短距离),而且奇偶性一致
if(!(x%2)&&even[a]<=x&&(even[a]||a==1)||x%2&&odd[a]<=x&&odd[a])cout<<"Yes\n";
else cout<<"No\n";
}
return 0;
}

1730

被折叠的 条评论
为什么被折叠?



