题目
算法标签: 并查集, T a r j a n Tarjan Tarjan算法, s c c scc scc强连通分量
思路
使用强连通分量算法求环上点的数量, 对每个连通分量求最小点数
T a r j a n Tarjan Tarjan算法求解代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int N = 200010, M = N;
int n;
int head[N], ed[M], ne[M], idx;
int stk[N], top;
int low[N], dfn[N], timestamp;
int id[N], scc_cnt, cnt[N];
bool in_stk[N];
void add(int u, int v) {
ed[idx] = v, ne[idx] = head[u], head[u] = idx++;
}
void tarjan(int u) {
dfn[u] = low[u] = ++timestamp;
stk[++top] = u, in_stk[u] = true;
for (int i = head[u]; ~i; i = ne[i]) {
int v = ed[i];
if (!dfn[v]) {
tarjan(v);
low[u] = min(low[u], low[v]);
}
else if (in_stk[v]) low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
++scc_cnt;
int v;
do {
v = stk[top--];
in_stk[v] = false;
id[v] = scc_cnt;
cnt[scc_cnt]++;
}
while (v != u);
}
}
int main() {
ios::sync_with_stdio(false);
cin.tie(0), cout.tie(0);
memset(head,-1, sizeof head);
cin >> n;
for (int i = 1; i <= n; ++i) {
int t;
cin >> t;
add(i, t);
}
for (int i = 1; i <= n; ++i) {
if (!dfn[i]) tarjan(i);
}
int ans = n;
for (int i = 1; i <= scc_cnt; ++i) {
if (cnt[i] > 1) ans = min(ans, cnt[i]);
}
cout << ans << "\n";
return 0;
}


京公网安备 11010502036488号