1 module dkh.graph.hldecomp; 2 3 import dkh.container.stackpayload; 4 5 struct HLInfo { 6 int[2][] id; //vertex -> [line id, line pos] 7 int[][] lines; //line id -> line list(top to bottom) 8 int[2][] par; //line id -> [parent line id, parent line pos] 9 int[] lineDPS; //line id -> line depth 10 this(size_t n) { 11 id = new int[2][n]; 12 } 13 } 14 15 /// calc lca(a, b) 16 int calcLCA(in HLInfo hl, int a, int b) { 17 import std.algorithm : swap; 18 with (hl) { 19 int[2] xl = id[a]; 20 int[2] yl = id[b]; 21 if (lineDPS[xl[0]] < lineDPS[yl[0]]) swap(xl, yl); 22 while (lineDPS[xl[0]] > lineDPS[yl[0]]) { 23 xl = par[xl[0]]; 24 } 25 while (xl[0] != yl[0]) { 26 xl = par[xl[0]]; 27 yl = par[yl[0]]; 28 } 29 if (xl[1] > yl[1]) swap(xl, yl); 30 return lines[xl[0]][xl[1]]; 31 } 32 } 33 34 HLInfo hlDecomposition(T)(in T g, int rt) { 35 auto n = g.length; 36 auto hl = HLInfo(n); 37 with (hl) { 38 int[] sz = new int[n]; 39 int calcSZ(int p, int b) { 40 sz[p] = 1; 41 foreach (e; g[p]) { 42 if (e.to == b) continue; 43 sz[p] += calcSZ(e.to, p); 44 } 45 return sz[p]; 46 } 47 calcSZ(rt, -1); 48 int idc = 0; 49 StackPayload!(int[2]) par_buf; 50 StackPayload!int line_buf, dps_buf; 51 void dfs(int p, int b, int height) { 52 line_buf ~= p; 53 id[p] = [idc, height]; 54 int nx = -1, buf = -1; 55 foreach (e; g[p]) { 56 if (e.to == b) continue; 57 if (buf < sz[e.to]) { 58 buf = sz[e.to]; 59 nx = e.to; 60 } 61 } 62 if (nx == -1) { 63 //make line 64 lines ~= line_buf.data.dup; 65 line_buf.clear; 66 idc++; 67 return; 68 } 69 70 dfs(nx, p, height+1); 71 foreach (e; g[p]) { 72 if (e.to == b || e.to == nx) continue; 73 par_buf ~= id[p]; 74 dps_buf ~= dps_buf.data[id[p][0]] + 1; 75 dfs(e.to, p, 0); 76 } 77 } 78 par_buf ~= [-1, -1]; 79 dps_buf ~= 0; 80 dfs(rt, -1, 0); 81 par = par_buf.data; 82 lineDPS = dps_buf.data; 83 } 84 return hl; 85 }