1 module dkh.graph.namori; 2 3 import dkh.graph.dfstree; 4 5 struct NamoriInfo { 6 bool[] isCycle; 7 int[][] cycles; 8 int[] root; 9 this(int n) { 10 isCycle = new bool[n]; 11 root = new int[n]; 12 } 13 } 14 15 Namori namori(T)(T g) { 16 import std.algorithm : find, each; 17 import std.range; 18 import std.conv : to; 19 int n = g.length.to!int; 20 auto info = dfsInfo(g); 21 auto nmr = NamoriInfo(n); 22 with (nmr) { 23 //find self loop 24 foreach (i; 0..n) { 25 if (g[i].find!(e => e.to == i).empty) continue; 26 isCycle[i] = true; 27 cycles ~= [i]; 28 } 29 foreach (p; info.vlis) { 30 if (info.low[p] == info.ord[p]) continue; 31 if (g[p].length == info.tr[p].length+1) continue; 32 int[] v; 33 int nw = p; 34 while (info.ord[nw] != info.low[p]) { 35 v ~= nw; 36 nw = info.par[nw]; 37 } 38 v ~= nw; 39 v.each!(i => isCycle[i] = true); 40 cycles ~= v; 41 } 42 bool[] used = new bool[n]; 43 void dfs(int p, int b, int r) { 44 if (used[p]) return; 45 used[p] = true; 46 root[p] = r; 47 foreach (e; g[p]) { 48 int d = e.to; 49 if (d == b) continue; 50 if (isCycle[d]) continue; 51 dfs(d, p, r); 52 } 53 } 54 foreach (i; 0..n) { 55 if (!isCycle[i]) continue; 56 dfs(i, -1, i); 57 } 58 } 59 return nmr; 60 } 61 62 NamoriInfo directedNamori(int[] g) { 63 import std.algorithm : find, each; 64 import std.range; 65 import std.conv : to; 66 int n = g.length.to!int; 67 auto nmr = NamoriInfo(n); 68 with (nmr) { 69 int[] used = new int[n]; used[] = -1; 70 foreach (i; 0..n) { 71 if (used[i] != -1) continue; 72 int j = i; 73 while (used[j] == -1) { 74 used[j] = i; 75 j = g[j]; 76 } 77 if (used[j] != i) continue; 78 int k = j; 79 int[] cy = []; 80 while (true) { 81 cy ~= k; 82 isCycle[k] = true; 83 if (g[k] == j) break; 84 k = g[k]; 85 } 86 cycles ~= cy; 87 } 88 int[] dp = new int[n]; dp[] = -1; 89 int dfs(int p) { 90 if (isCycle[p]) return p; 91 if (dp[p] != -1) return dp[p]; 92 return dp[p] = dfs(g[p]); 93 } 94 foreach (i; 0..n) { 95 root[i] = dfs(i); 96 } 97 } 98 return nmr; 99 }