2019CSP-J T4 加工零件
题目描述
凯凯的工厂正在有条不紊地生产一种神奇的零件,神奇的零件的生产过程自然也很神奇。工厂里有 n 位工人,工人们从 1 ∼n 编号。某些工人之间存在双向的零件传送带。保证每两名工人之间最多只存在一条传送带。
如果 x 号工人想生产一个被加工到第 L(L>1) 阶段的零件,则所有与 x 号工人有传送带直接相连的工人,都需要生产一个被加工到第 L - 1 阶段的零件(但 x 号工人自己无需生产第 L - 1 阶段的零件)。
如果 x 号工人想生产一个被加工到第 1 阶段的零件,则所有与 x 号工人有传送带直接相连的工人,都需要为 x 号工人提供一个原材料。
轩轩是 1 号工人。现在给出 q 张工单,第 i 张工单表示编号为 ai 的工人想生产一个第 Li 阶段的零件。轩轩想知道对于每张工单,他是否需要给别人提供原材料。他知道聪明的你一定可以帮他计算出来!
输入格式
第一行三个正整数 n,m 和 q,分别表示工人的数目、传送带的数目和工单的数目。
接下来 m 行,每行两个正整数 u 和 v,表示编号为 u 和 v 的工人之间存在一条零件传输带。保证 u 不等于 v。
接下来 q 行,每行两个正整数 a 和 L,表示编号为 a 的工人想生产一个第 L 阶段的零件。
输出格式
共 q 行,每行一个字符串 Yes
或者 No
。如果按照第 i 张工单生产,需要编号为 1 的轩轩提供原材料,则在第 i 行输出 Yes
;否则在第 i 行输出 No
。注意输出不含引号。
正文开始:
这个题不难看出(我当时死活没看出来)是个奇偶数最短路(瞎起的名字),大体意思就是,一个位置要单数零件,和他相邻单数长度且长度不超过零件等级的位置都要提供原料。(想象2个工人互相给零件,距离原点的距离和原点零件等级跟最后谁做原零件都是有关系的)
我们可以用链式前向星建图,广搜遍历,每到达一个新的点还要判断这次的距离是不是更短,要把距离1号点的奇偶数距离记成最小的。不可以只记有没有,万一1号点做2号零件,你距离1号点100格远,肯定用不到你。对了,广搜有个剪枝,如果这个点的奇偶距离都没变,哪继续求就没意义了,之前肯定进过队列,所以直接抛弃它。
一号点可以和任何一个相邻的点循环给零件,所以一号点距离1号点的初始值是0。(为什么不能是2,又不会制作等级0的零件? 因为要根据1号点距离自己的偶数位置求其他点的奇数位置。)
上一句话有个地方有点重要(任何一个相邻的点),重点不是任何,是相邻的点,我们要特判,如果一号没有相邻的点,输入什么都输出0。上面的初始偶数距离是0也不管用。
可能会奇妙的转圈圈,所以奇偶数的初始值要定义的很大。
差不多就这样,不会链式前向星的同学可以去翻看之前的博客
代码:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
#include<cmath>
#include<cstring>
using namespace std;
queue<long long>bj;
long long shu=1,a[100005],p,n,m,z1,z2,ji[100005],ou[100005],f;
struct hehe
{
long long w,nxt;
}sz[200005];
void add(long long z1,long long z2)
{
sz[shu].nxt=a[z1];
sz[shu].w=z2;
a[z1]=shu;
shu++;
}
void bfs()
{
bj.push(1);
ou[1]=0;
while(bj.empty()!=true)
{
long long bl=bj.front();
bj.pop();
for(long long i=a[bl];i!=0;i=sz[i].nxt)
{
if(ou[bl]+1<ji[sz[i].w]||ji[bl]+1<ou[sz[i].w])
{
bj.push(sz[i].w);
}
ji[sz[i].w]=min(ji[sz[i].w],ou[bl]+1);
ou[sz[i].w]=min(ou[sz[i].w],ji[bl]+1);
}
}
}
int main()
{
scanf("%lld%lld%lld",&n,&m,&p);
for(long long i=1;i<=100005;i++)
{
ji[i]=99999999;
ou[i]=99999999;
}
for(long long i=0;i<m;i++)
{
scanf("%lld%lld",&z1,&z2);
add(z1,z2);
add(z2,z1);
if(z1==1||z2==1)
{
f=1;
}
}
bfs();
for(long long i=0;i<p;i++)
{
scanf("%lld%lld",&z1,&z2);
if(f!=1)
{
cout<<"No"<<endl;
continue;
}
if(ou[z1]<=z2&&z2%2==0)
{
cout<<"Yes"<<endl;
continue;
}
if(ji[z1]<=z2&z2%2==1)
{
cout<<"Yes"<<endl;
continue;
}
cout<<"No"<<endl;
}
return 0;
}
当时可能傻了吧。
最新文章
- PHP通过XML报文格式的POST请求方式,与第三方接口交互(发送xml,获取XML,并解析xml步骤)
- tomcat4 请求的处理——初步分析
- CSS选择符详解
- PHPStorm Xdebug配置
- 关闭SSMS的事务自动提交,改为手动提交
- IOS开发--数据持久化篇之文件存储(一)
- WordPress 模板常用函数
- MySql Error: Can&#39;t update table in stored function/trigger
- 生成N个不重复的随机数(转)
- Boost Thread学习笔记三
- linux sed命令详解(转)
- 1572: [Usaco2009 Open]工作安排Job[贪心]
- js的call() ,apply() 两种方法的区别和用法,最白话文的解释,让枯燥滚粗!
- Spark技术内幕:Master的故障恢复
- ABP框架系列之二十八:(Handling-Exceptions-异常处理)
- 安装Microsoft SQL server Management Studio Express 2005 错误码是29506解决方案
- 分形之希尔伯特-皮亚诺(Hilbert-Peano)曲线
- Unit Testing of Spring MVC Controllers: Configuration
- 汽车学习---汽车知识大全【all】
- ThinkPHP3.2设置异常页面404跳转页面