CF1272E Nearest Opposite Party(思维+BFS)

题意:

给出一串序列,在位置为i的元素上,你可以向i+a[i]或i-a[i]的位置跳跃,前提是这两个位置在1到n的范围内。

请你计算每个节点,跳跃到与这个节点的元素值奇偶性不同的节点的最少步数。

题解:

反向建图,然后设两个超级源点,一个表示奇数,一个表示偶数,然后所有点向这两个源点连边,从这两个源点向外做BFS,搜到的步数减1就是最短距离。

#include<bits/stdc++.h>
using namespace std;
const int maxn=2e5+100;
int a[maxn];
//可以预处理出每个节点向左向右的位置 
 
int n;
vector<int> g[maxn];
int visit[maxn];
int d[maxn][2];//表示当前节点到最近的奇数or偶数的距离 
struct node {
    int u;
    int d;
};
void bfs(int s,int f) {
    queue<node> q;
    memset(visit,0,sizeof(visit));
    q.push({s,0});
    visit[s]=1;
    while (!q.empty()) {
        node u=q.front();
        q.pop();
        for (int i=0;i<g[u.u].size();i++) {
            int v=g[u.u][i];
            if (visit[v]) continue;
            q.push({v,u.d+1});
            visit[v]=1;
            d[v][f]=u.d+1;
        }
    }
}
 
int main () {
    scanf("%d",&n);
    for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    for (int i=1;i<=n;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]&1)
            g[n+1].push_back(i);
        else
            g[n+2].push_back(i); 
    }
    bfs(n+1,1);
    bfs(n+2,0);
    for (int i=1;i<=n;i++) {
        printf("%d ",d[i][1-a[i]%2]-1);
    }
}
原文地址:https://www.cnblogs.com/zhanglichen/p/13111060.html