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