朴素做法:对每一个起点跑一遍,用一个布尔数组记录是否访问过,时间复杂度O\!\left(n^2\right)

优化:找出所有的环,答案为最近的环上点。时间复杂度O\!\left(n\right)

#include <iostream>
#include <vector>
using namespace std;

int n;
vector<int> p;
vector<int> res;

void Dfs(int x) {
    res[x] = -1;
    int y = p[x];
    if (res[y] == -1) {
        res[y] = y;
        while (y != x) {
            y = p[y];
            res[y] = y;
        }
    }
    if (res[x] != -1) {
        return;
    }
    if (res[y] == 0) {
        Dfs(y);
    }
    if (res[x] == -1) {
        res[x] = res[y];
    }
}

void Solve() {
    cin >> n;
    p.resize(n + 1);
    res.resize(n + 1);
    for (int i = 1; i <= n; i++) {
        cin >> p[i];
    }
    for (int i = 1; i <= n; i++) {
        if (res[i] == 0) {
            Dfs(i);
        }
        cout << abs(res[i]) << ' ';
    }
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    Solve();
}
// 64 位输出请用 printf("%lld")