function shortcut_all(p) = let pp = p->p; in if eql(p,pp) then pp else shortcut_all(pp) $ function compress_graph(P,E) = let % update edges to point to new parent % e1,e2 = unzip(e); e = {(i,j): i in p->e1; j in p->e2}; % remove self edges and flip edges up % e = {if i > j then (j,i) else (i,j) : (i,j) in e | i /= j}; % identify roots, relabel roots, and relabel edges % roots = {p == i : p in p ; i in [0:#p]}; labels = enumerate(roots); e1,e2 = unzip(e); e = {(li,lj): li in labels->e1; lj in labels->e2} in (e,pack_index(roots)) $ function hybrid_connected_components(E,n) = if #E == 0 then [0:n] else let P = shortcut_all([0:n]<-E); (E,I) = compress_graph(P,E); R = hybrid_connected_components(E,#I); Ins = P <- zip(I, I->R); in Ins->Ins $ edges = [(1, 5), (5, 6), (1, 6), (6, 10), (4, 5), (13, 4), (2, 13), (2, 11), (9, 2), (12, 9), (8, 9), (3, 7)]; hybrid_connected_components(edges,14);