1 条题解

  • 0
    @ 2025-8-24 22:13:07

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar kradcigam
    永不放弃之心,将成为贯穿逆境之光!

    搬运于2025-08-24 22:13:07,当前版本为作者最后更新于2019-11-23 18:14:21,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    博客园体验更佳

    讲讲我的做法

    确定做法

    首先,看到这道题,我直接想到的是递归,于是复杂度就上天了,考虑最短路

    如何用最短路

    首先,看一张图

    360截图16251114373524.png

    我们该如何解决问题?

    问题:3355阶段的零件11要不要做呢?

    其实,实质就是看3311有没有长度为55的路径。

    问题:3377阶段的零件11要不要做呢?

    其实,实质就是看3311有没有长度为77的路径。

    问题:3366阶段的零件11要不要做呢?

    其实,实质就是看3311有没有长度为66的路径。

    仔细思考这33个问题,我们会发现,如果3311有长度为55的路径,那么3311一定有长度为77的路径,但并不一定有长度为66的路径。

    所以,我们要对每个点求一遍奇数路径,和偶数路径。

    实现最短路

    最短路的算法有很多,这道题最好用dijkstradijkstra,或bfsbfs

    这道题的时限并不紧,并且dijkstradijkstra细节太多,我就来演示bfsbfs实现的最短路

    void bfw(){//我有一个好朋友叫bfw,所以我写bfs时,喜欢把函数名起为bfw
    	memset(ji,0x3f,sizeof(ji));//奇数最短路径
    	memset(ou,0x3f,sizeof(ou));//偶数最短路径
    	queue<pair<int,int> >q;
    	q.push(make_pair(1,0));
        ou[1]=0;
    	while(q.size()){
    		int x=q.front().first,y=q.front().second;
    		for(int i=0;i<v[x].size();i++){
    			if(y%2==1){//奇数+1=偶数
    				if(y+1<ou[v[x][i]]){
    					ou[v[x][i]]=y+1;//更新答案
    					q.push(make_pair(v[x][i],y+1));
    				}
    			}else{//偶数+1=奇数
    				if(y+1<ji[v[x][i]]){
    					ji[v[x][i]]=y+1;//更新答案
    					q.push(make_pair(v[x][i],y+1));
    				}
    			}
    		}
    		q.pop();
    	}
    }
    

    vv数组是一个动态数组,也就是vectorvector,曹老师教我们多用STLSTL写程序

    如果你写这样的bfsbfs民间数据会WAWA 11个点 ,这个点是这样的

    360截图172905077510285.png

    11号点是一个孤点,没有偶数路径,所以,我们的bfsbfs要这么写

    void bfw(){//我有一个好朋友叫bfw,所以我写bfs时,喜欢把函数名起为bfw
    	memset(ji,0x3f,sizeof(ji));//奇数最短路径
    	memset(ou,0x3f,sizeof(ou));//偶数最短路径
    	queue<pair<int,int> >q;
    	for(int i=0;i<v[1].size();i++){
    		ji[v[1][i]]=1;
    		q.push(make_pair(v[1][i],1));
    	}
    	while(q.size()){
    		int x=q.front().first,y=q.front().second;
    		for(int i=0;i<v[x].size();i++){
    			if(y%2==1){//奇数+1=偶数
    				if(y+1<ou[v[x][i]]){
    					ou[v[x][i]]=y+1;//更新答案
    					q.push(make_pair(v[x][i],y+1));
    				}
    			}else{//偶数+1=奇数
    				if(y+1<ji[v[x][i]]){
    					ji[v[x][i]]=y+1;//更新答案
    					q.push(make_pair(v[x][i],y+1));
    				}
    			}
    		}
    		q.pop();
    	}
    }
    

    简要讲解主程序

    有了这些主程序应该是很简单的了

    int main(){
    	int n,m,q;
    	read(n);read(m);read(q);
    	for(int i=1;i<=m;i++){
    		int x,y;
    		read(x);read(y);//无向边
    		v[x].push_back(y);//连边
    		v[y].push_back(x);//连边
    	}
    	bfw();//跑最短路
    	while(q--){
    		int x,y;
    		read(x);read(y);
    		if(y%2==0){
    			if(ou[x]>y)puts("No");//如果大于就不可能了
    			else puts("Yes");
    		}else{
    			if(ji[x]>y)puts("No");//如果大于就不可能了
    			else puts("Yes");
    		}
    	}
    	return 0;
    }
    

    总结

    先来看一看这题完整的代码了

    #include <bits/stdc++.h>
    using namespace std;
    template<typename T>inline void read(T &FF){
    	T RR=1;FF=0;char CH=getchar();
    	for(;!isdigit(CH);CH=getchar())if(CH=='-')RR=-1;
    	for(;isdigit(CH);CH=getchar())FF=(FF<<1)+(FF<<3)+(CH^48);
    	FF*=RR;
    }
    template<typename T>void write(T x){
    	if(x<0)putchar('-'),x*=-1;
    	if(x>9)write(x/10);
    	putchar(x%10+48);
    }
    vector<int>v[100010];
    int ji[100010],ou[100010];
    void bfw(){//我有一个好朋友叫bfw,所以我写bfs时,喜欢把函数名起为bfw
    	memset(ji,0x3f,sizeof(ji));//奇数最短路径
    	memset(ou,0x3f,sizeof(ou));//偶数最短路径
    	queue<pair<int,int> >q;
    	for(int i=0;i<v[1].size();i++){
    		ji[v[1][i]]=1;
    		q.push(make_pair(v[1][i],1));
    	}
    	while(q.size()){
    		int x=q.front().first,y=q.front().second;
    		for(int i=0;i<v[x].size();i++){
    			if(y%2==1){//奇数+1=偶数
    				if(y+1<ou[v[x][i]]){
    					ou[v[x][i]]=y+1;//更新答案
    					q.push(make_pair(v[x][i],y+1));
    				}
    			}else{//偶数+1=奇数
    				if(y+1<ji[v[x][i]]){
    					ji[v[x][i]]=y+1;//更新答案
    					q.push(make_pair(v[x][i],y+1));
    				}
    			}
    		}
    		q.pop();
    	}
    }
    int main(){
    	int n,m,q;
    	read(n);read(m);read(q);
    	for(int i=1;i<=m;i++){
    		int x,y;
    		read(x);read(y);//无向边
    		v[x].push_back(y);//连边
    		v[y].push_back(x);//连边
    	}
    	bfw();//跑最短路
    	while(q--){
    		int x,y;
    		read(x);read(y);
    		if(y%2==0){
    			if(ou[x]>y)puts("No");//如果大于就不可能了
    			else puts("Yes");
    		}else{
    			if(ji[x]>y)puts("No");//如果大于就不可能了
    			else puts("Yes");
    		}
    	}
    	return 0;
    }
    

    这道题还是比较有思维含量的,民间数据也出的很好,让我们思考全面。

    最后,还是希望大家不懂就在评论区问,觉得好就点赞!

    • 1

    信息

    ID
    4662
    时间
    1000ms
    内存
    250MiB
    难度
    4
    标签
    递交数
    0
    已通过
    0
    上传者