2020 BIT冬训-图&&DFS&&BFS I - Nearest Opposite Parity CodeForces - 1272E(图上BFS)

Problem Description

You are given an array aa consisting of n integers. In one move, you can jump from the position ii to the position i−ai (if 1iai) 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 aiai (i.e. if aiai is odd then aj has to be even and vice versa).

Input

The first line of the input contains one integer n (1n2105) — the number of elements in a.

The second line of the input contains nn integers a1,a2,,an (1≤ai≤n), where aiai is the ii-th element of a.

Output

Print n integers d1,d2,,dn, where di is the minimum the number of moves required to reach any position 

such that aj has the opposite parity from ai (i.e. if ai is odd then aj has to be even and vice versa) or -1 if it is impossible to reach such a position.

Example

Input
10
4 5 7 6 7 5 4 4 6 4
Output
1 1 1 2 -1 1 1 3 1 1 

这题需要用到反向建边和寻找最短路。由于边权都为1故BFS即可(spfa和dijkstra还不太会qwq)
反向建边指的是从终点指向起点(即能够到达下标的点)。这样方便记录。(如果正向建边。即记录下标能够到达的点)
参考链接
AC代码如下:
#include <algorithm>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<vector>
#include<random>
#include<ctime> 
#include<queue>
#define MAXN 200005
using namespace std;
int n;
vector<int>g[MAXN];
queue<int>q;
int a[MAXN],odd[MAXN],even[MAXN]; 
int main(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1;i<=n;i++){//记录哪些i能到i-a[i],i+a[i]的位置 。反向建边 
        if(i-a[i]>=1)
            g[i-a[i]].push_back(i);
        if(i+a[i]<=n)
            g[i+a[i]].push_back(i);
    }
    for(int i=1;i<=n;i++){//先计算每个数到奇数的最短距离。同上。 
        if(a[i]%2){//将奇数压入栈 
            odd[i]=0;
            q.push(i);
        }else
            odd[i]=-1;
    }
    while(!q.empty()){
        int u = q.front();
        q.pop();
        int s = g[u].size();
        for(int i=0;i<s;i++){
            int v=g[u][i];//v为能到u的点 
            if(odd[v]==-1||odd[v]>odd[u]+1){//如果该点为偶数且未赋值或者赋值过后找到更小的步数。则更新 
                odd[v] = odd[u]+1;
                q.push(v);
            }
        }
    }
    for(int i=1;i<=n;i++){//之后计算每个数到偶数的最短距离,同上 
        if(a[i]%2==0){
            even[i]=0;
            q.push(i);
        }else
            even[i]=-1;
    }
    while(!q.empty()){
        int u = q.front();
        q.pop();
        int s = g[u].size();
        for(int i=0;i<s;i++){
            int v=g[u][i];
            if(even[v]==-1||even[v]>even[u]+1){
                even[v] = even[u]+1;
                q.push(v);
            }
        }
    }
    for(int i=1;i<=n;i++){
        if(a[i]%2)
            printf("%d ",even[i]);
        else
            printf("%d ",odd[i]);
    }
    return 0;
}

 

 
posted @ 2021-03-02 17:25  mikku  阅读(43)  评论(0)    收藏  举报