import java.util.*; import java.util.stream.Stream; public class DijkstraSegmentTree { public static void shortestPaths(List[] edges, int s, long[] prio, int[] pred) { Arrays.fill(pred, -1); Arrays.fill(prio, Long.MAX_VALUE); prio[s] = 0; long[] t = new long[edges.length * 2]; Arrays.fill(t, Long.MAX_VALUE); set(t, s, 0); while (true) { int cur = minIndex(t); if (t[cur + t.length / 2] == Long.MAX_VALUE) break; set(t, cur, Long.MAX_VALUE); for (Edge e : edges[cur]) { int v = e.t; long nprio = prio[cur] + e.cost; if (prio[v] > nprio) { prio[v] = nprio; pred[v] = cur; set(t, v, nprio); } } } } public static class Edge { int t; int cost; public Edge(int t, int cost) { this.t = t; this.cost = cost; } } static void set(long[] t, int i, long value) { i += t.length / 2; if (t[i] < value && value != Long.MAX_VALUE) return; t[i] = value; for (; i > 1; i >>= 1) t[i >> 1] = Math.min(t[i], t[i ^ 1]); } static int minIndex(long[] t) { int res = 1; while (res < t.length / 2) res = res * 2 + (t[res * 2] > t[1] ? 1 : 0); return res - t.length / 2; } // Usage example public static void main(String[] args) { int[][] cost = {{0, 3, 2}, {0, 0, -2}, {0, 0, 0}}; int n = cost.length; List[] edges = Stream.generate(ArrayList::new).limit(n).toArray(List[]::new); for (int i = 0; i < n; i++) { for (int j = 0; j < n; j++) { if (cost[i][j] != 0) { edges[i].add(new Edge(j, cost[i][j])); } } } long[] dist = new long[n]; int[] pred = new int[n]; shortestPaths(edges, 0, dist, pred); System.out.println(0 == dist[0]); System.out.println(3 == dist[1]); System.out.println(1 == dist[2]); System.out.println(-1 == pred[0]); System.out.println(0 == pred[1]); System.out.println(1 == pred[2]); } }