package class16; import java.util.ArrayList; import java.util.Arrays; import java.util.PriorityQueue; // 课上没有讲这个题,这是我给同学们找的练习题 // leetcode 743题,可以用这道题来练习Dijkstra算法 // 测试链接 : https://leetcode.com/problems/network-delay-time public class Code06_NetworkDelayTime { // 方法一 : 普通堆 + 屏蔽已经计算过的点 public static int networkDelayTime1(int[][] times, int n, int k) { ArrayList> nexts = new ArrayList<>(); for (int i = 0; i <= n; i++) { nexts.add(new ArrayList<>()); } for (int[] delay : times) { nexts.get(delay[0]).add(new int[] { delay[1], delay[2] }); } PriorityQueue heap = new PriorityQueue<>((a, b) -> a[1] - b[1]); heap.add(new int[] { k, 0 }); boolean[] used = new boolean[n + 1]; int num = 0; int max = 0; while (!heap.isEmpty() && num < n) { int[] record = heap.poll(); int cur = record[0]; int delay = record[1]; if (used[cur]) { continue; } used[cur] = true; num++; max = Math.max(max, delay); for (int[] next : nexts.get(cur)) { if (!used[next[0]]) { heap.add(new int[] { next[0], delay + next[1] }); } } } return num < n ? -1 : max; } // 方法二 : 加强堆的解法 public static int networkDelayTime2(int[][] times, int n, int k) { ArrayList> nexts = new ArrayList<>(); for (int i = 0; i <= n; i++) { nexts.add(new ArrayList<>()); } for (int[] delay : times) { nexts.get(delay[0]).add(new int[] { delay[1], delay[2] }); } Heap heap = new Heap(n); heap.add(k, 0); int num = 0; int max = 0; while (!heap.isEmpty()) { int[] record = heap.poll(); int cur = record[0]; int delay = record[1]; num++; max = Math.max(max, delay); for (int[] next : nexts.get(cur)) { heap.add(next[0], delay + next[1]); } } return num < n ? -1 : max; } // 加强堆 public static class Heap { public boolean[] used; public int[][] heap; public int[] hIndex; public int size; public Heap(int n) { used = new boolean[n + 1]; heap = new int[n + 1][2]; hIndex = new int[n + 1]; Arrays.fill(hIndex, -1); size = 0; } public void add(int cur, int delay) { if (used[cur]) { return; } if (hIndex[cur] == -1) { heap[size][0] = cur; heap[size][1] = delay; hIndex[cur] = size; heapInsert(size++); } else { int hi = hIndex[cur]; if (delay <= heap[hi][1]) { heap[hi][1] = delay; heapInsert(hi); } } } public int[] poll() { int[] ans = heap[0]; swap(0, --size); heapify(0); used[ans[0]] = true; hIndex[ans[0]] = -1; return ans; } public boolean isEmpty() { return size == 0; } private void heapInsert(int i) { int parent = (i - 1) / 2; while (heap[i][1] < heap[parent][1]) { swap(i, parent); i = parent; parent = (i - 1) / 2; } } private void heapify(int i) { int l = (i * 2) + 1; while (l < size) { int smallest = l + 1 < size && heap[l + 1][1] < heap[l][1] ? (l + 1) : l; smallest = heap[smallest][1] < heap[i][1] ? smallest : i; if (smallest == i) { break; } swap(smallest, i); i = smallest; l = (i * 2) + 1; } } private void swap(int i, int j) { int[] o1 = heap[i]; int[] o2 = heap[j]; int o1hi = hIndex[o1[0]]; int o2hi = hIndex[o2[0]]; heap[i] = o2; heap[j] = o1; hIndex[o1[0]] = o2hi; hIndex[o2[0]] = o1hi; } } }