import core.bitop;
import core.checkedint;
import core.simd;
import core.stdc.stdio;
import core.stdc.stdlib;
import core.stdc.string;
import std.algorithm;
import std.array;
import std.ascii;
import std.bigint;
import std.bitmanip;
import std.complex;
import std.container;
import std.conv;
import std.datetime;
import std.format;
import std.functional;
import std.math;
import std.meta;
import std.numeric;
import std.random;
import std.range;
import std.regex;
//import std.stdio;
import std.string;
import std.typecons;
import std.variant;

__gshared:

/+
bool read(T...)(T ptrs) if (ptrs.length > 0) {
    return readf(' ' ~ replicate("%s ", ptrs.length), ptrs) == ptrs.length;
}
+/

T[ ] allocate(T)(size_t n) {
    return (cast(T*)malloc(n * T.sizeof))[0 .. n];
}

auto pairwise(R)(R range) if (isForwardRange!R) {
    return lockstep(range, dropOne(range));
}

struct Dsu(int n) {
    int[n] p;

    void init() {
        iota(n).copy(p[ ]);
    }

    int get(int x) {
        return x == p[x] ? x : (p[x] = get(p[x]));
    }

    void merge(int x, int y) {
        p[get(x)] = get(y);
    }
}

int n;
Dsu!10_000 dsu;

void main() {
    scanf("%d", &n);
    dsu.init();
    foreach (i; 0 .. n) {
        int x;
        scanf("%d", &x);
        dsu.merge(i, x - 1);
    }
    int result = 0;
    foreach (i; 0 .. n)
        if (i == dsu.get(i))
            result++;
    printf("%d\n", result);
}
