There is a \"Weighted Quick-Union with Path Compression\" algorithm.
The code:
public class WeightedQU
{
private int[] id;
private int[] iz;
Question 1. It is not right to say that the line id[i] = id[id[i]]; only reaches the second ancestor of the root.You will realize that while loop while(i != id[i]) stops only when the node i is pointing at the root i.e when i == id[i].By this time we shall have pointed the node to the root using the line id[i] = id[id[i]]; where the inner id[i] is the root.
Question 2.
You are wrong to initialize iz[i] = i; actually it should be iz[i] = 1; meaning, each and every node size is initialized by 1 at the beginning since they are of size 1. In the union function you realize that we have the lines iz[j] += iz[i]; and iz[i] += iz[j]; which updates the size of the root node to be the sum of the sizes of the two components joined together. This efficiently updates the nodes sizes.