| package old; |
|
|
| import java.util.*; |
| import java.util.function.Consumer; |
|
|
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| public class clique2_ablations_compat { |
|
|
| public static List<SnapshotDTO> runLaplacianRMC(List<Integer>[] adj1Based) { |
| ArrayList<SnapshotDTO> out = new ArrayList<>(); |
| runLaplacianRMCStreaming(adj1Based, out::add); |
| return out; |
| } |
|
|
| public static void runLaplacianRMCStreaming(List<Integer>[] adj1Based, |
| Consumer<SnapshotDTO> sink) { |
| final int n = adj1Based.length - 1; |
| int[][] nbrs = new int[n][]; |
| int[] degFull = new int[n]; |
| for (int u1 = 1; u1 <= n; u1++) { |
| List<Integer> lst = adj1Based[u1]; |
| int m = lst.size(); |
| int[] arr = new int[m]; |
| for (int i = 0; i < m; i++) arr[i] = lst.get(i) - 1; |
| nbrs[u1 - 1] = arr; |
| degFull[u1 - 1] = m; |
| } |
|
|
| |
| int[] order = (n <= 100_000) ? degeneracyOrderStable(nbrs, degFull) |
| : degeneracyOrderBucket(nbrs, degFull); |
|
|
| DSU dsu = new DSU(n); |
| boolean[] added = new boolean[n]; |
| int[] degC = new int[n]; |
| |
| double[] S3 = new double[n]; |
| double[] P = new double[n]; |
|
|
| for (int step = n - 1; step >= 0; step--) { |
| final int u = order[step]; |
| added[u] = true; |
| dsu.makeSingleton(u); |
|
|
| |
| int[] Nu = nbrs[u]; |
| int t = 0; |
| for (int v : Nu) if (added[v]) t++; |
|
|
| |
| int[] neigh = new int[t]; |
| int k = 0; |
| long sum_b = 0L; |
| long sum_b2 = 0L; |
| for (int v : Nu) { |
| if (!added[v]) continue; |
| neigh[k++] = v; |
| int b = degC[v]; |
| sum_b += b; |
| sum_b2 += (long) b * (long) b; |
| } |
|
|
| |
| int ru = dsu.find(u); |
| for (int i = 0; i < t; i++) { |
| int rv = dsu.find(neigh[i]); |
| if (ru != rv) ru = dsu.union(ru, rv); |
| } |
|
|
| |
| |
| double deltaS3 = (double) t * t * t + 3.0 * (double) sum_b2 + 3.0 * (double) sum_b + (double) t; |
|
|
| |
| |
| double deltaP = 0.0; |
| for (int i = 0; i < t; i++) { |
| int v = neigh[i]; |
| int b = degC[v]; |
| |
| int rv = dsu.find(v); |
| long sNv = 0L; |
| for (int w : nbrs[v]) { |
| if (!added[w]) continue; |
| if (dsu.find(w) != rv) continue; |
| sNv += degC[w]; |
| } |
| deltaP += (double) t * (double) (b + 1) + (double) sNv; |
| } |
|
|
| |
| S3[ru] += deltaS3; |
| P[ru] += deltaP; |
|
|
| |
| int[] nodes = dsu.nodesOf(ru); |
| long sumDegIn2 = dsu.sumDegIn2(ru); |
| double Q = 2.0 * (S3[ru] - P[ru]); |
| sink.accept(new SnapshotDTO(nodes, nodes.length, sumDegIn2, Q)); |
|
|
| |
| degC[u] += t; |
| for (int i = 0; i < t; i++) { |
| int v = neigh[i]; |
| degC[v] += 1; |
| } |
| } |
| } |
|
|
| |
|
|
| static int[] degeneracyOrderStable(int[][] nbrs, int[] deg0) { |
| final int n = nbrs.length; |
| int[] deg = Arrays.copyOf(deg0, n); |
| boolean[] removed = new boolean[n]; |
| PriorityQueue<long[]> pq = new PriorityQueue<>(Comparator.comparingLong(a -> (a[0] << 21) | a[1])); |
| for (int u = 0; u < n; u++) pq.add(new long[]{deg[u], u}); |
| int[] order = new int[n]; |
| int ptr = 0; |
| while (ptr < n) { |
| long[] top = pq.poll(); |
| int du = (int) top[0]; |
| int u = (int) top[1]; |
| if (removed[u] || du != deg[u]) continue; |
| removed[u] = true; |
| order[ptr++] = u; |
| for (int v : nbrs[u]) if (!removed[v]) { |
| deg[v]--; |
| pq.add(new long[]{deg[v], v}); |
| } |
| } |
| return order; |
| } |
|
|
| static int[] degeneracyOrderBucket(int[][] nbrs, int[] deg0) { |
| final int n = nbrs.length; |
| int maxDeg = 0; |
| for (int d : deg0) if (d > maxDeg) maxDeg = d; |
|
|
| int[] deg = Arrays.copyOf(deg0, n); |
| int[] head = new int[Math.max(2, maxDeg + 2)]; |
| int[] next = new int[n]; |
| int[] prev = new int[n]; |
| Arrays.fill(head, -1); |
| Arrays.fill(next, -1); |
| Arrays.fill(prev, -1); |
| for (int u = 0; u < n; u++) { |
| int d = deg[u]; |
| next[u] = head[d]; |
| if (head[d] >= 0) prev[head[d]] = u; |
| head[d] = u; |
| } |
|
|
| boolean[] removed = new boolean[n]; |
| int[] order = new int[n]; |
| int ptr = 0; |
| int cur = 0; |
| while (cur <= maxDeg && head[cur] < 0) cur++; |
|
|
| for (int it = 0; it < n; it++) { |
| while (cur <= maxDeg && head[cur] < 0) cur++; |
| if (cur > maxDeg) cur = maxDeg; |
| int u = head[cur]; |
| head[cur] = next[u]; |
| if (head[cur] >= 0) prev[head[cur]] = -1; |
| next[u] = prev[u] = -1; |
| removed[u] = true; |
| order[ptr++] = u; |
|
|
| for (int v : nbrs[u]) if (!removed[v]) { |
| int dv = deg[v]; |
| int pv = prev[v], nv = next[v]; |
| if (pv >= 0) next[pv] = nv; else head[dv] = nv; |
| if (nv >= 0) prev[nv] = pv; |
| int nd = dv - 1; |
| deg[v] = nd; |
| next[v] = head[nd]; |
| if (head[nd] >= 0) prev[head[nd]] = v; |
| prev[v] = -1; |
| head[nd] = v; |
| if (nd < cur) cur = nd; |
| } |
| } |
| return order; |
| } |
|
|
| |
|
|
| static final class DSU { |
| final int n; |
| final int[] parent; |
| final int[] size; |
| final long[] sumDegIn2; |
| final IntList[] members; |
|
|
| DSU(int n) { |
| this.n = n; |
| this.parent = new int[n]; |
| this.size = new int[n]; |
| this.sumDegIn2 = new long[n]; |
| this.members = new IntList[n]; |
| for (int i = 0; i < n; i++) { |
| parent[i] = i; |
| size[i] = 0; |
| sumDegIn2[i] = 0L; |
| members[i] = new IntList(); |
| } |
| } |
|
|
| void makeSingleton(int u) { |
| parent[u] = u; |
| size[u] = 1; |
| sumDegIn2[u] = 0L; |
| members[u].clear(); |
| members[u].add(u); |
| } |
|
|
| int find(int x) { |
| int r = x; |
| while (r != parent[r]) r = parent[r]; |
| int y = x; |
| while (y != r) { int p = parent[y]; parent[y] = r; y = p; } |
| return r; |
| } |
|
|
| int union(int ra, int rb) { |
| ra = find(ra); rb = find(rb); |
| if (ra == rb) return ra; |
| if (size[ra] < size[rb]) { int t = ra; ra = rb; rb = t; } |
| parent[rb] = ra; |
| size[ra] += size[rb]; |
| sumDegIn2[ra] += sumDegIn2[rb]; |
| members[ra].addAll(members[rb]); |
| members[rb].clear(); |
| return ra; |
| } |
|
|
| long sumDegIn2(int r) { return sumDegIn2[find(r)]; } |
|
|
| int[] nodesOf(int r) { |
| return members[find(r)].toArray(); |
| } |
| } |
|
|
| |
| static final class IntList { |
| int[] a; int sz; |
| IntList() { a = new int[4]; sz = 0; } |
| void clear() { sz = 0; } |
| void add(int x) { if (sz == a.length) a = Arrays.copyOf(a, sz << 1); a[sz++] = x; } |
| void addAll(IntList other) { |
| if (other.sz == 0) return; |
| int need = sz + other.sz; |
| if (need > a.length) { |
| int cap = a.length; |
| while (cap < need) cap <<= 1; |
| a = Arrays.copyOf(a, cap); |
| } |
| System.arraycopy(other.a, 0, a, sz, other.sz); |
| sz = need; |
| } |
| int[] toArray() { return Arrays.copyOf(a, sz); } |
| } |
|
|
| |
|
|
| public static final class SnapshotDTO { |
| public final int[] nodes; |
| public final int nC; |
| public final long sumDegIn; |
| public final double Q; |
|
|
| public SnapshotDTO(int[] nodes, int nC, long sumDegIn, double Q) { |
| this.nodes = nodes; |
| this.nC = nC; |
| this.sumDegIn = sumDegIn; |
| this.Q = Q; |
| } |
| } |
| } |
|
|