本题链接
从叶子(尚未访问过的节点)往上找其最远的祖先,若能找到根,则合题;若找到环或找到与树不连通的祖先,则将祖先的父亲指向根。
#include <bits/stdc++.h>
namespace FastIO {
char buf[1 << 21], buf2[1 << 21], a[20], *p1 = buf, *p2 = buf, hh = '\n';
int p, p3 = -1;
void read() {}
void print() {}
inline int getc() {
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++;
}
inline void flush() {
fwrite(buf2, 1, p3 + 1, stdout), p3 = -1;
}
template<typename T, typename... T2>
inline void read(T &x, T2 &... oth) {
int f = 0;
x = 0;
char ch = getc();
while (!isdigit(ch)) {
if (ch == '-')
f = 1;
ch = getc();
}
while (isdigit(ch)) {
x = x * 10 + ch - 48;
ch = getc();
}
x = f ? -x : x;
read(oth...);
}
template<typename T, typename... T2>
inline void print(T x, T2... oth) {
if (p3 > 1 << 20)
flush();
if (x < 0)
buf2[++p3] = 45, x = -x;
do {
a[++p] = x % 10 + 48;
} while (x /= 10);
do {
buf2[++p3] = a[p];
} while (--p);
buf2[++p3] = hh;
print(oth...);
}
} // namespace FastIO
#define read FastIO::read
#define print FastIO::print
//======================================
using namespace std;
const int maxn=2e5+10;
typedef long long ll;
int n,m,dep[maxn],root,cnt,fa[maxn],ans,in[maxn],t;
void work(int u) {
dep[u] = ++cnt;
while (!dep[fa[u]]) {
u = fa[u];
dep[u]=cnt;
}
if (dep[fa[u]] == cnt) {
if (root == 0) root = u;
if (fa[u]!=root){
ans++;
fa[u] = root;
}
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("1.txt", "r", stdin);
//freopen("2.txt", "w", stdout);
#endif
//======================================
read(n);
for (int i = 1; i <= n; i++) {
read(fa[i]);
if (fa[i] == i) root = i;
}
for (int i = 1; i <= n; i++) {
if (!dep[i]) {
work(i);
}
}
print(ans);
FastIO::hh = ' ';
for (int i = 1; i <= n; i++) {
print(fa[i]);
}
//======================================
FastIO::flush();
return 0;
}