time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given an array a consisting of n integers. In one move, you can jump from the position i to the position i−ai (if 1≤i−ai) or to the position i+ai (if i+ai≤n).
For each position i from 1 to n you want to know the minimum the number of moves required to reach any position j such that aj has the opposite parity from ai (i.e. if ai is odd then aj has to be even and vice versa).
input
10
4 5 7 6 7 5 4 4 6 4
output
1 1 1 2 -1 1 1 3 1 1
/// spfa最最短路,建立两个超级源点,一个连接奇数点一个链接偶数点,在建边的时候,边权设置为 1
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn = 2e6 + 7;
typedef int itn;
int n;
int a[maxn];
struct Node{
int u;
int v;
int next;
int w;
}edge[maxn];
int cnt;
int head[maxn];
int dis[maxn];
itn ans[maxn];
itn vis[maxn];
void _Init(){
cnt = 0;
for(int i=0;i<maxn;i++) head[i] = -1;
}
void _Add(int u,int v){
edge[cnt].u = u;
edge[cnt].v = v;
edge[cnt].w = 1;
edge[cnt].next = head[u];
head[u] = cnt ++;
}
void _SPFA(int u){
for(int i=1;i<maxn;i++){
dis[i] = 0x3f3f3f3f;
vis[i] = 0;
}
dis[u] = 0;
vis[u] = 1;
queue<int> que;
///cout << que.size() <<endl;
que.push(u);
while(que.size()){
int t = que.front();
que.pop();
vis[t] = 0;
for(int i = head[t]; ~i;i = edge[i].next){
int to = edge[i].v;
if(dis[to] > dis[t] + edge[i].w){
dis[to] = dis[t] + edge[i].w;
if(vis[to] == 0){
que.push(to);
vis[to] = 1;
}
}
///puts("ok");
}
}
}
int main(){
cin >> n;
_Init();
for(int i=1;i<=n;i++) cin >> a[i];
for(int i=1;i<=n;i++){
if(i - a[i] >= 1) _Add(i - a[i],i);
if(i + a[i] <= n) _Add(i + a[i],i);
if(a[i] % 2 == 0) _Add(n+1,i);
else _Add(n+2,i);
}
_SPFA(n + 1);
///puts("okay");
for(int i=1;i<=n;i++){
if(a[i] % 2) ans[i] = dis[i];
}
_SPFA(n + 2);
for(int i=1;i<=n;i++){
if(a[i] % 2 == 0) ans[i] = dis[i];
}
for(int i=1;i<=n;i++){
if(ans[i] == 0x3f3f3f3f) printf("-1 ");
else printf("%d ",ans[i] - 1);
}
///cout << 0x3f3f3f3f <<endl;
return 0;
}