題解 P5663 【加工零件【民間數據】】


博客園體驗更佳

講講我的做法

確定做法

首先,看到這道題,我直接想到的是遞歸,於是復雜度就上天了,考慮最短路

如何用最短路

首先,看一張圖

360截圖16251114373524.png

我們該如何解決問題?

問題:\(3\)\(5\)階段的零件\(1\)要不要做呢?

其實,實質就是看\(3\)\(1\)有沒有長度為\(5\)的路徑。

問題:\(3\)\(7\)階段的零件\(1\)要不要做呢?

其實,實質就是看\(3\)\(1\)有沒有長度為\(7\)的路徑。

問題:\(3\)\(6\)階段的零件\(1\)要不要做呢?

其實,實質就是看\(3\)\(1\)有沒有長度為\(6\)的路徑。

仔細思考這\(3\)個問題,我們會發現,如果\(3\)\(1\)有長度為\(5\)的路徑,那么\(3\)\(1\)一定有長度為\(7\)的路徑,但並不一定有長度為\(6\)的路徑。

所以,我們要對每個點求一遍奇數路徑,和偶數路徑。

實現最短路

最短路的算法有很多,這道題最好用\(dijkstra\),或\(bfs\)

這道題的時限並不緊,並且\(dijkstra\)細節太多,我就來演示\(bfs\)實現的最短路

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();
	}
}

\(v\)數組是一個動態數組,也就是\(vector\),曹老師教我們多用\(STL\)寫程序

如果你寫這樣的\(bfs\)民間數據會\(WA\) \(1\)個點 ,這個點是這樣的

360截圖172905077510285.png

\(1\)號點是一個孤點,沒有偶數路徑,所以,我們的\(bfs\)要這么寫

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;
}

這道題還是比較有思維含量的,民間數據也出的很好,讓我們思考全面。

最后,還是希望大家不懂就在評論區問,覺得好就點贊!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM