-
Notifications
You must be signed in to change notification settings - Fork 2
/
Solution.java
165 lines (122 loc) · 4.11 KB
/
Solution.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
package hackrank.algorithm.graph.bfsreach;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.stream.Collectors;
/**
* Breadth First Search: Shortest Reach
*
* @see https://www.hackerrank.com/challenges/bfsshortreach
*/
public class Solution {
public static void main(String[] args) {
for (Graph graph : readInput(System.in)) {
graph.computeDistancesFromStart();
List<Integer> distances = graph.findDistancesFromStart();
System.out.println(distances.stream().map(i -> String.valueOf(i)).collect(Collectors.joining(" ")));
}
}
private static List<Graph> readInput(InputStream input) {
Scanner scanner = new Scanner(input);
int testCases = scanner.nextInt();
List<Graph> graphs = new ArrayList<>(testCases);
for (int i = 0; i < testCases; i++) {
int numberNodes = scanner.nextInt();
int numberEdges = scanner.nextInt();
int[][] edges = new int[numberEdges][];
for (int e = 0; e < numberEdges; e++) {
edges[e] = new int[] { scanner.nextInt(), scanner.nextInt() };
}
int startNodeId = scanner.nextInt();
graphs.add(new Graph(numberNodes, edges, startNodeId));
}
scanner.close();
return graphs;
}
}
class Graph {
public Map<Integer, Node> nodes;
public int startNodeId;
public Graph(int numberNodes, int[][] edges, int startNodeId) {
this.nodes = new HashMap<>(numberNodes, 1.0f);
for (int nodeId = 1; nodeId <= numberNodes; nodeId++) {
nodes.put(nodeId, new Node(nodeId));
}
for (int[] edge : edges) {
connect(edge[0], edge[1]);
}
this.startNodeId = startNodeId;
}
public void connect(int idFrom, int idTo) {
Node from = nodes.get(idFrom);
Node to = nodes.get(idTo);
from.connect(to, 6);
to.connect(from, 6);
}
public void computeDistancesFromStart() {
Node nodeStart = nodes.get(startNodeId);
nodeStart.minDistance = 0;
PriorityQueue<Node> vertexQueue = new PriorityQueue<Node>();
vertexQueue.add(nodeStart);
while (!vertexQueue.isEmpty()) {
Node nodeFrom = vertexQueue.poll();
for (Edge connection : nodeFrom.edges) {
Node nodeTo = connection.target;
int distanceTo = nodeFrom.minDistance + connection.weight;
if (distanceTo < nodeTo.minDistance) {
vertexQueue.remove(nodeTo);
nodeTo.minDistance = distanceTo;
nodeTo.previous = nodeFrom;
vertexQueue.add(nodeTo);
}
}
}
}
public int findDistanceTo(int endId) {
int distance = nodes.get(endId).minDistance;
return distance != Integer.MAX_VALUE ? distance : -1;
}
public List<Integer> findDistancesFromStart() {
List<Integer> distances = new ArrayList<>();
for (int nodeId = 1; nodeId <= nodes.size(); nodeId++) {
if (nodeId == startNodeId) {
continue;
}
distances.add(findDistanceTo(nodeId));
}
return distances;
}
}
class Node implements Comparable<Node> {
public int id;
public List<Edge> edges;
public int minDistance = Integer.MAX_VALUE;
public Node previous;
public Node(int id) {
this.id = id;
this.edges = new ArrayList<>();
}
public void connect(Node square, int weight) {
edges.add(new Edge(square, weight));
}
@Override
public String toString() {
return String.valueOf(id);
}
@Override
public int compareTo(Node other) {
return Integer.compare(minDistance, other.minDistance);
}
}
class Edge {
public Node target;
public int weight;
public Edge(Node target, int weight) {
this.target = target;
this.weight = weight;
}
}