code: public int[] unionFind() {
          byte[] rank = new byte[nodeCount];
          int[] root = new int[nodeCount];
          for (int nodeId = 0; nodeId < nodeCount; nodeId++) root[nodeId] = nodeId;
  
          runProgram((x, y) -> {
              while (x != root[x]) x = root[x];
              while (y != root[y]) y = root[y];
              if (x != y) {
                  if (rank[x] >= rank[y]) {
                      root[y] = x;
                      if (rank[x] == rank[y]) rank[x] += 1;
                  } else {
                      root[x] = y;
                  }
              }
          });
          return root;
      }
docs: /*
  fn union_find<G: EdgeMapper>(graph: &G, nodes: u32) {
  let mut root: Vec<u32> = (0..nodes).collect();
  let mut rank: Vec<u8> = (0..nodes).map(|_| 0u8).collect();
  graph.map_edges(|mut x, mut y| {
  while x != root[x] { x = root[x]; }
  while y != root[y] { y = root[y]; }
  if x != y {
  match rank[x].cmp(&rank[y]) {
  Less    => root[x] = y,
  Greater => root[y] = x,
  Equal   => { root[y] = x; rank[x] += 1 },
  }
  }
  });
  }