有 n 個網絡節點,標記為 1 到 n。
給你一個列表 times,表示信號經過 有向 邊的傳遞時間。 times[i] = (ui, vi, wi),其中 ui 是源節點,vi 是目標節點, wi 是一個信號從源節點傳遞到目標節點的時間。
現在,從某個節點 K 發出一個信號。需要多久才能使所有節點都收到信號?如果不能使所有節點收到信號,返回 -1 。
來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/network-delay-time
著作權歸領扣網絡所有。商業轉載請聯系官方授權,非商業轉載請注明出處。
無負權
時間復雜度:O(eloge)、O(elogn)
每次從離源點最近的節點開始拓展
系統堆
import java.util.*;
class Solution {
public static int networkDelayTime(int[][] times, int n, int k) {
if (times == null || times.length == 0 || times[0].length == 0) {
return 0;
}
Graph graph = new Graph();
for (int[] time : times) {
graph.addEdge(time[0], time[1], time[2]);
}
PriorityQueue<Info> queue = new PriorityQueue<>(new Comparator<Info>() {
@Override
public int compare(Info o1, Info o2) {
return Integer.compare(o1.value, o2.value);
}
});
Set<Integer> visited = new HashSet<>();
Map<Integer, Integer> distanceMap = new HashMap<>();
distanceMap.put(k, 0);
queue.offer(new Info(k, 0));
while (!queue.isEmpty()) {
Info from = queue.poll();
visited.add(from.index);
for (Graph.Edge edge : graph.getNode(from.index).nexts) {
if (!visited.contains(edge.to.value)) {
int distance = distanceMap.getOrDefault(edge.to.value, Integer.MAX_VALUE);
if (distance > edge.weight + distanceMap.get(from.index)) {
distance = edge.weight + distanceMap.get(from.index);
distanceMap.put(edge.to.value, distance);
queue.offer(new Info(edge.to.value, distance));
}
}
}
}
if (distanceMap.size() < n) {
return -1;
}
int ret = Integer.MIN_VALUE;
for (Map.Entry<Integer, Integer> entry : distanceMap.entrySet()) {
ret = Math.max(ret, entry.getValue());
}
return ret;
}
public static void main(String[] args) {
int[][] time = {{2, 1, 1}, {2, 3, 1}, {3, 4, 1}};
int n = 4;
int k = 2;
System.out.println(networkDelayTime(time, n, k));
}
}
class Info {
int index;
int value;
public Info(int index, int value) {
this.index = index;
this.value = value;
}
}
class Graph {
private final Map<Node, Map<Node, Edge>> edgeMap;
private final Map<Integer, Node> nodeMap;
private final List<Edge> edges;
public Graph() {
this.edgeMap = new HashMap<>();
this.nodeMap = new HashMap<>();
this.edges = new ArrayList<>();
}
public Node buildNode(int value) {
Node node = nodeMap.get(value);
if (node == null) {
node = new Node(value);
nodeMap.put(value, node);
}
return node;
}
public Node getNode(int value) {
return nodeMap.get(value);
}
public Edge buildEdge(Node from, Node to, int weight) {
Map<Node, Edge> fromEdgeMap = edgeMap.computeIfAbsent(from, k -> new HashMap<>());
Edge edge = fromEdgeMap.get(to);
if (edge == null) {
edge = new Edge(from, to, weight);
fromEdgeMap.put(to, edge);
from.out++;
to.in++;
from.nexts.add(edge);
edges.add(edge);
} else {
if (edge.weight > weight) {
edge.weight = weight;
}
}
return edge;
}
public Edge addEdge(int from, int to, int weight) {
return buildEdge(buildNode(from), buildNode(to), weight);
}
class Node {
int value;
int in;
int out;
List<Edge> nexts;
public Node(int value) {
this.value = value;
this.in = 0;
this.out = 0;
this.nexts = new ArrayList<>();
}
}
class Edge {
Node from;
Node to;
int weight;
public Edge(Node from, Node to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
}
}
}
自定義堆
import java.util.*;
class Solution {
public static int networkDelayTime(int[][] times, int n, int k) {
Graph graph = Graph.buildGraph(times);
Map<Node, Integer> distanceMap = new HashMap<>();
Node from = graph.buildNode(k);
Map<Node, Map<Node, Edge>> edgeMap = graph.getEdgeMap();
Map<Node, Edge> fromEdgeMap = edgeMap.get(from);
if (fromEdgeMap == null || fromEdgeMap.size() == 0) {
return -1;
}
Heap queue = new Heap(n);
queue.offer(new Info(from, 0));
Set<Node> visited = new HashSet<>();
while (!queue.isEmpty()) {
Info poll = queue.poll();
visited.add(poll.node);
for (Edge edge : poll.node.nexts) {
if (!visited.contains(edge.to)) {
Integer toDistance = distanceMap.getOrDefault(edge.to, Integer.MAX_VALUE);
if (poll.distance + edge.weight < toDistance) {
distanceMap.put(edge.to, poll.distance + edge.weight);
Info info = new Info(edge.to, poll.distance + edge.weight);
if (queue.has(info)) {
queue.update(info);
} else {
queue.offer(info);
}
}
}
}
}
int res = Integer.MIN_VALUE;
int connect = 0;
for (Map.Entry<Node, Integer> entry : distanceMap.entrySet()) {
connect++;
res = Math.max(res, entry.getValue());
}
return connect != n - 1 ? -1 : res;
}
public static void main(String[] args) {
int[][] times = {{4, 2, 76}, {1, 3, 79}, {3, 1, 81}, {4, 3, 30}, {2, 1, 47}, {1, 5, 61}, {1, 4, 99},
{3, 4, 68}, {3, 5, 46}, {4, 1, 6}, {5, 4, 7}, {5, 3, 44}, {4, 5, 19}, {2, 3, 13},
{3, 2, 18}, {1, 2, 0}, {5, 1, 25}, {2, 5, 58}, {2, 4, 77}, {5, 2, 74}};
int n = 5, k = 3;
System.out.println(networkDelayTime(times, n, k));
}
}
class Info {
Node node;
int distance;
public Info(Node node, int distance) {
this.node = node;
this.distance = distance;
}
}
class Graph {
private Map<Node, Map<Node, Edge>> edgeMap = new HashMap<>();
private Map<Integer, Node> nodeMap = new HashMap<>();
private List<Edge> edges = new ArrayList<>();
public List<Edge> getEdges() {
return edges;
}
public Map<Node, Map<Node, Edge>> getEdgeMap() {
return edgeMap;
}
public Map<Integer, Node> getNodeMap() {
return nodeMap;
}
public Node buildNode(int index) {
Node node = nodeMap.get(index);
if (node == null) {
node = new Node(index);
nodeMap.put(index, node);
}
return node;
}
public Edge buildEdge(Node from, Node to, int weight) {
Map<Node, Edge> nodeEdgeMap = edgeMap.computeIfAbsent(from, k -> new HashMap<>());
Edge edge = nodeEdgeMap.get(to);
if (edge == null) {
edge = new Edge(from, to, weight);
nodeEdgeMap.put(to, edge);
edges.add(edge);
from.out++;
to.in++;
from.nexts.add(edge);
} else {
if (edge.weight > weight) {
edge.weight = weight;
}
}
return edge;
}
public void addEdge(int fromIndex, int toIndex, int weight) {
buildEdge(buildNode(fromIndex), buildNode(toIndex), weight);
}
public static Graph buildGraph(int[][] times) {
if (times == null || times.length == 0 || times[0].length == 0) {
return new Graph();
}
Graph graph = new Graph();
for (int i = 0; i < times.length; ++i) {
graph.addEdge(times[i][0], times[i][1], times[i][2]);
}
return graph;
}
}
class Edge {
Node from;
Node to;
int weight;
public Edge(Node from, Node to, int weight) {
this.from = from;
this.to = to;
this.weight = weight;
}
}
class Node {
int value;
int in;
int out;
List<Edge> nexts;
public Node(int value) {
this.value = value;
this.in = 0;
this.out = 0;
this.nexts = new ArrayList<>();
}
}
class Heap {
private Info[] data;
private int limit;
private int size;
private Map<Node, Integer> indexMap;
public int parent(int index) {
return (index - 1) >> 1;
}
public int left(int index) {
return index << 1 | 1;
}
public int right(int index) {
return (index << 1 | 1) + 1;
}
public Heap(int limit) {
this.limit = limit;
this.data = new Info[limit];
this.size = 0;
this.indexMap = new HashMap<>();
}
public void swap(int a, int b) {
if (a == b) {
return;
}
Info tmp = data[a];
data[a] = data[b];
data[b] = tmp;
indexMap.put(data[a].node, a);
indexMap.put(data[b].node, b);
}
public boolean has(Info info) {
return indexMap.containsKey(info.node);
}
public void offer(Info info) {
data[size] = info;
indexMap.put(info.node, size);
heapifyUp(size++);
}
public void heapifyUp(int index) {
while (index != 0) {
int parent = parent(index);
if (data[parent].distance > data[index].distance) {
swap(parent, index);
index = parent;
} else {
break;
}
}
}
public void heapifyDown(int index) {
int left, right;
while (index < size && (left = left(index)) < size) {
int minIndex = index;
if (data[left].distance < data[minIndex].distance) {
minIndex = left;
}
if ((right = right(index)) < size && data[right].distance < data[minIndex].distance) {
minIndex = right;
}
if (minIndex == index) {
break;
}
swap(index, minIndex);
index = minIndex;
}
}
public void update(Info info) {
Integer index = indexMap.get(info.node);
data[index] = info;
heapifyUp(index);
heapifyDown(index);
}
public boolean isEmpty() {
return this.size == 0;
}
public boolean isFull() {
return this.size == limit;
}
public Info poll() {
if (isEmpty()) {
throw new RuntimeException("空");
}
Info res = data[0];
swap(0, --size);
indexMap.remove(res.node);
heapifyDown(0);
return res;
}
}