#nullable enable #region var (_input, _iter) = (Array.Empty(), 0); T I() where T : IParsable { while (_iter >= _input.Length) (_input, _iter) = (Console.ReadLine()!.Trim().Split(' '), 0); return T.Parse(_input[_iter++], null); } #endregion static T[] Range(int n, Func F) => Enumerable.Range(0, n).Select(_ => F()).ToArray(); var n = I(); var az = Range(n, () => I() - 1); var uf = new UnionFind(n); for (var i = 0; i < n; i++) uf.Union(i, az[i]); var ans = 0; for (var i = 0; i < n; i++) if (uf.Find(i) == i) ans++; Console.WriteLine(ans); class UnionFind { int[] Verticals { get; set; } public UnionFind(int verticals) { Verticals = new int[verticals]; Verticals.AsSpan().Fill(-1); } public int Union(int x, int y) { (x, y) = (Find(x), Find(y)); if (x == y) return x; var (sx, sy) = (Size(x), Size(y)); if (sx < sy) (x, y, sy) = (y, x, sx); Verticals[x] -= sy; return Verticals[y] = x; } public int Find(int x) { var p = Verticals[x]; if (p < 0) return x; return Verticals[x] = Find(p); } public int Size(int x) => -Verticals[Find(x)]; }