题意:
给出一串序列,在位置为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); } }