洛谷P5663 [CSP-J2019] 加工零件

传送门:P5663 [CSP-J2019] 加工零件

这是一篇写于 2024.8.17 的做题记录,祝稻米朋友们节日快乐。

废话还是少说一点比较好qwq

题目意思:(一个很抽象的东西)

说白了其实就是给你一张无向图,然后有 p 次询问,每次询问给你一个 v 和 L ,问你从 1 号点到 v 号点 有没有 长度为 L 的边。

注意:
  • 每条边是可以重复走的
  • 这是一张无向图
  • 可能会有孤点的情况

思路:

自信满满的开题 qwq
然鹅。。。
不会啊!!!!
瞬间开启自我怀疑状态
翻了翻题解,判断奇偶是什么东西???
于是。。。
思考ing。。。。
终于!

如果 L 与 从点 1 出发到达该点的路径长度 奇偶性一致
换句话说就是:
如果 L 是奇数,并且从 1 号点出发有一条能到达该点的 路径长度为奇数,路径长度 <= L 的边
那么他就需要提供原材料,因为该材料在加工过程中能在相邻两个工人之间来回横跳
偶数情况亦然
所以我们只需要求 1 到所有点的奇数路径 和 偶数路径
看是否有与 L 奇偶性相同的边,且长度<=L
为了保证长度<=L,我们求 1到所有点的奇数最短路偶数最短路
思路明确了就很好写了 QaQ

最终代码:

就跑一个最短路啦
SPFA,启动!

#include<bits/stdc++.h>

using namespace std;

const int maxn=100100;
const int maxm=100100;
 
int m,n,qq;
int en=0;
int fir[maxn];

struct edge{
	int v;
	int next;
}ed[maxm*2];

void add_edge(int u,int v)
{
	en++;
	ed[en].v=v;
	ed[en].next=fir[u];
	fir[u]=en;
}

int jdist[maxn],odist[maxn];
bool inque[maxn];
queue<int> q;

void spfa(int r)
{
	memset(jdist,0x3f3f3f,sizeof(jdist));
	memset(odist,0x3f3f3f,sizeof(odist));
	odist[r]=0;
	q.push(r);
	inque[r]=true;
	while(!q.empty())
	{
		int now=q.front();
		q.pop();
		inque[now]=false;
		for(int i=fir[now];i;i=ed[i].next)
		{
			int v=ed[i].v;
			if(odist[v]>jdist[now]+1||jdist[v]>odist[now]+1){
				jdist[v]=min(jdist[v],odist[now]+1);
				odist[v]=min(odist[v],jdist[now]+1);
				if(!inque[v])
				{
					q.push(v);
					inque[v]=true;
				}
			}
		}
	}
 } 

int main()
{
	cin>>n>>m>>qq;
	for(int i=1;i<=m;i++)
	{
		int u,v;
		cin>>u>>v;
		add_edge(u,v);
		add_edge(v,u);
	}
	spfa(1);
	while(qq--)
	{
		int v,l;
		cin>>v>>l;
		if(l%2==1&&jdist[v]<=l)cout<<"Yes"<<endl;
		else if(l%2==0&&odist[v]<=l)cout<<"Yes"<<endl;
		else cout<<"No"<<endl;
	 }
	return 0; 
}

后记

  • 因为用的是 SPFA ,孤点的情况对代码运行结果就没有影响了 qwq
  • 这个题目保证了同一个点不会入队两次inque数组其实没用。。时间复杂度为 O(n+q)
  • 最后,对于边权为 1 的图来跑最短路,bfs 的方法也是可行的,复杂度与 spfa 一致
posted @ 2024-08-17 14:54  lazy_ZJY  阅读(10)  评论(0编辑  收藏  举报