tarjan做法显然是违背出题人意图的。
本题限制了每个点只有一条出边,所以不存在复杂回路,如果成环,只存在简单环。
于是可以直接DFS,如果成环,就把整个回路都置为回路上点的数量。
#include <bits/stdc++.h> #define sc(x) scanf("%lld", &(x)) #define pr(x) printf("%lld\n", (x)) #define rep(i, l, r) for (int i = (l); i <= (r); ++i) using namespace std; typedef long long ll; const int N = 1e6 + 7; const int mod = 1e9 + 7; int a[N], ans[N], c; // ans[i]表示从i出发能到达多少个点 bool vis[N]; int dfs(int u) { vis[u] = 1; int v = a[u]; //导向点 if (vis[v]) { //访问过 if (ans[v] == 0) c = v; //成环 return ans[u] = ans[v] + 1; //连接 } else return ans[u] = dfs(v) + 1; //深度+1 } void check(int u, int v) { //把整个回路修正 ans[u] = ans[v]; if (a[u] != v) check(a[u], v); } int main() { ios::sync_with_stdio(false), cin.tie(0), cout.tie(0); int n; cin >> n; rep(i, 1, n) cin >> a[i]; rep(i, 1, n) if (!vis[i]) { c = -1; //回路的起点,dfs跑完以后ans[c]就记录了环上有多少个点 dfs(i); //如果成环 整个环上都是简单路径可收纳的点 if (c != -1) check(c, c); } int res = 0; cout << res << '\n'; return 0; }