2019CSP-J T4 加工零件

前言:每次参加CSP都慌的一批,回来之后才发现真的有够水。/(ㄒoㄒ)/~~(又要去普及,害怕再挂)

大家可以自己去百度题目描述。

这个题不难看出(我当时死活没看出来)是个奇偶数最短路(瞎起的名字),大体意思就是,一个位置要单数零件,和他相邻单数长度且长度不超过零件等级的位置都要提供原料。(想象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;
}

 当时可能傻了吧。

 

猜你喜欢

转载自www.cnblogs.com/lichangjian/p/12572029.html