关于此题:
1.咋一看,不就是无脑dfs吗。一通乱码,然后 wawawawawa。。。。。。
经过仔细思考 反反复复举例
从 【 8 : 2 2 1 3 4 5 6 7;】 发现一丝端倪。
第七个点7(6) 的路径应该为2,却跑出了-1;
调试以后发现问题所在:
如果dfs 第一个点的话 1(2)>3(1)>2(2)>4(3)>7(6) 当转移到第7个点的时候 ,离的6最短的奇偶性相异的点是3(1),而此时并3(1)并没有更新为最短路所以无法用来更新7(6);所以7(6)的得到的答案是错误的。。
dfs(行不通)。。
下面说下正确的解法(bfs):
如果把题当作图的话,此题可以看作每个点至多有两条权值为1的出路的单向有环图。只需bfs一轮图即可。
步骤:
1。开两个数组odd【maxn】,even[maxn]。(odd[i],表示第i个点到第一个为奇数的点的路长,even[i]为到偶数点的路长)若a[i]为奇数,则odd[i]=0。反之,even[i]=0;
2.反向存边。
3.bfs跑一轮图
4.输出结果。
(先贴一个愚蠢的dfs,引以为戒,图论题还是得用图的解法)
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
#include <stack>
#include <bitset>
#define ll long long
using namespace std;
const int maxn=200000+10;
int n;
int a[maxn];
int dpji[maxn];
int dpou[maxn];
int vis[maxn];
void dfs(int x){
if(vis[x])return;
vis[x]=1;
if(x-a[x]>=1){
dfs(x-a[x]);
dpji[x]=min(dpji[x],dpji[x-a[x]]+1);
dpou[x]=min(dpou[x],dpou[x-a[x]]+1);
}
if(x+a[x]<=n){
dfs(x+a[x]);
dpji[x]=min(dpji[x],dpji[x+a[x]]+1);
dpou[x]=min(dpou[x],dpou[x+a[x]]+1);
}
}
int main(){
memset(vis,0,sizeof(vis));
cin>>n;
for(int i=1;i<=n;i++){
dpou[i]=200010;
dpji[i]=200010;
}
for(int i=1;i<=n;i++){
cin>>a[i];
if(a[i]&1)dpji[i]=0;
else dpou[i]=0;
}
for(int i=1;i<=n;i++){
dfs(i);
}
for(int i=1;i<=n;i++){
if(a[i]&1){
if(dpou[i]==200010)cout<<-1<<' ';
else cout<<dpou[i]<<' ';
}
else {
if(dpji[i]==200010)cout<<-1<<' ';
else cout<<dpji[i]<<' ';
}
}
return 0;
}
BFS
```cpp
#include <queue>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
#include <map>
#include <stack>
#include <bitset>
#define ll long long
using namespace std;
const int maxn=2e5+10;
int n;
int odd[maxn];
int even[maxn];
int vis[maxn][2];
int first[maxn];
int a[maxn];
queue<int>q[2];
struct edge{
int to,next;
}e[maxn*2];
int tol=0;
void addedge(int v,int from){
tol++;
e[tol].to=v;
e[tol].next=first[from];
first[from]=tol;
}
void cal(){
while(!q[0].empty()){
int now=q[0].front();q[0].pop();
vis[now][0]=0;
for (int i = first[now]; i; i=e[i].next)
{
if(odd[e[i].to]>odd[now]+1){
odd[e[i].to]=odd[now]+1;
if(!vis[e[i].to][0])q[0].push(e[i].to);
}
}
}
while(!q[1].empty()){
int now=q[1].front();q[1].pop();
vis[now][1]=0;
for (int i = first[now]; i; i=e[i].next)
{
if(even[e[i].to]>even[now]+1){
even[e[i].to]=even[now]+1;
if(!vis[e[i].to][1])q[1].push(e[i].to);
}
}
}
}
int main(){
cin>>n;
memset(odd,0x1f,sizeof(odd));
memset(even,0x1f,sizeof(even));
memset(first,0,sizeof(first));
memset(vis,0,sizeof(vis));
for (int i=1; i<=n; i++){
cin>>a[i];
if(a[i]%2==1){
odd[i]=0;
q[0].push(i);
vis[i][0]=1;
if(i-a[i]>=1)addedge(i,i-a[i]);
if(i+a[i]<=n)addedge(i,i+a[i]);
}
else {
even[i]=0;
q[1].push(i);
vis[i][1]=1;
if(i-a[i]>=1)addedge(i,i-a[i]);
if(i+a[i]<=n)addedge(i,i+a[i]);
}
}
cal();
for(int i=1;i<=n;i++){
if(a[i]&1){
if(even[i]==0x1f1f1f1f)cout<<-1;
else cout<<even[i];
}
else{
if(odd[i]==0x1f1f1f1f)cout<<-1;
else cout<<odd[i];
}
cout<<' ';
}
return 0;
}