VP链接:https://codeforces.com/gym/104891
J. Teleportation
最短路。
以 i -> 和 i -> i + 1 为边,建立有向图。由于所有指向 0 节点的边,在跑最短路算法的时候都会被舍弃掉,因为 dis[0] = 0,所以可以建立一个新的节点 n,让原本指向 0 节点的边指向 n 节点。
时间复杂度:,m 是边的数量。
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
int n, x, a[N], dis[N], head[N], vis[N], num = 0;
struct edge { int to, nxt; } e[N << 2];
struct node {
int pos, d;
bool operator < (const node &x) const {
return x.d < d;
}
};
priority_queue<node> q;
inline int read() {
int x = 0, f = 1; char c = getchar();
while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); }
while (c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
return x * f;
}
void addEdge(int u, int v) { e[++num] = (edge){v, head[u]}, head[u] = num; }
void dij() {
for (int i = 0; i <= n; i++) dis[i] = INT_MAX, vis[i] = 0;
dis[0] = 0; q.push({0, 0});
while (!q.empty()) {
node cur = q.top(); q.pop();
if (vis[cur.pos]) continue;
vis[cur.pos] = 1;
for (int i = head[cur.pos]; i != -1; i = e[i].nxt) {
int v = e[i].to;
if (dis[v] > dis[cur.pos] + 1) {
dis[v] = dis[cur.pos] + 1;
q.push({v, dis[v]});
}
}
}
}
int main() {
n = read(), x = read();
for(int i = 0; i < n; i++) a[i] = read();
for (int i = 0; i <= n; i++) {
head[i] = -1;
int v = (i + a[i % n]) % n;
if (v == 0) v = n;
addEdge(i, v);
if (i) {
v = i + 1;
if (v > n) v = 1;
addEdge(i, v);
}
}
dij(); // dijsktra
printf("%d", dis[x]);
return 0;
}

332

被折叠的 条评论
为什么被折叠?



