博客園體驗更佳
講講我的做法
確定做法
首先,看到這道題,我直接想到的是遞歸,於是復雜度就上天了,考慮最短路。
如何用最短路
首先,看一張圖

我們該如何解決問題?
問題:\(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\)個點 ,這個點是這樣的

\(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;
}
這道題還是比較有思維含量的,民間數據也出的很好,讓我們思考全面。
最后,還是希望大家不懂就在評論區問,覺得好就點贊!
