Sizes Of The Arguments

void union_sets(int a, int b) {
    if (size[a] < size[b])       // line 2
        swap(a, b);
    a = find_set(a);
    b = find_set(b);
    if (a != b) {
        parent[b] = a;
        size[a] += size[b];
    }
}

The two optimizations are both present, but line 2 was hoisted above the two find_set calls. Which input makes this version behave measurably worse than the correct one?

A

None. size is only ever read on roots anyway, so hoisting the comparison is safe.

B

union_sets(i, 0) for i = 1, 2, ..., n-1, where every call passes a singleton as the first argument and a growing component as the second.

C

Any sequence in which the same pair is united twice, because size[a] += size[b] then double counts.

D

A sequence of n/2 unions on disjoint pairs, because no size entry ever exceeds 2.