- import java.util.Arrays; 
- import java.util.HashMap; 
- import java.util.Map; 
- import java.util.Map.Entry; 
- import java.util.TreeSet; 
- import java.util.stream.Collectors; 
-   
- class Ideone { 
- 	public static void-  main (String[]-  args ) {
 
- 		test1(); 
- 		test2(); 
- 	} 
- 	public static void test1() { 
- 		Graph graph = new Graph(); 
- 		graph.addEdge(0, 1, 4); 
- 		graph.addEdge(0, 2, 3); 
- 		graph.addEdge(1, 2, 1); 
- 		graph.addEdge(1, 3, 2); 
- 		graph.addEdge(2, 3, 4); 
- 		graph.addEdge(3, 4, 2); 
- 		graph.addEdge(4, 5, 6); 
- 		graph.startAt(0); 
- 		System- . out- . println(- graph. getPath(5));
 
- 	} 
- 	public static void test2() { 
- 		Graph graph = new Graph(); 
- 		graph.addEdge(0, 1, 4); 
- 		graph.addEdge(0, 2, 3); 
- 		graph.addEdge(1, 3, 2); 
- 		graph.addEdge(1, 2, 5); 
- 		graph.addEdge(2, 3, 7); 
- 		graph.addEdge(3, 4, 2); 
- 		graph.addEdge(4, 0, 4); 
- 		graph.addEdge(4, 1, 4); 
- 		graph.addEdge(4, 5, 6); 
- 		graph.startAt(0); 
- 		System- . out- . println(- graph. getPath(5));
 
- 	} 
- } 
- final class Graph { 
- 	private static final class Node { 
- 		final int no; 
- 		Map<Node, Integer> edges = new HashMap<>(); 
- 		Node[] path; 
- 		int pathWeight; 
- 		Node(int no) { 
- 			this.no = no; 
- 		} 
- 	} 
-   
- 	private-  Map <Integer- , Node >-  nodes  = new-  HashMap <>();
 
-   
- 	public void addEdge(int sourceNo, int destinationNo, int weight) { 
- 		Node source = this.nodes.computeIfAbsent(sourceNo, Node::new); 
- 		Node dest = this.nodes.computeIfAbsent(destinationNo, Node::new); 
- 		source.edges.put(dest, weight); 
- 		dest.edges.put(source, weight); 
- 	} 
-   
- 	public void startAt(int startNo) { 
- 		this.nodes.values().forEach(n -> n.path = null); 
- 		Node source = this.nodes.computeIfAbsent(startNo, Node::new); 
- 		source.path = new Node[] { source }; 
- 		source.pathWeight = 0; 
- 		TreeSet <- Node >-  pending  = new-  TreeSet <>((- a, b ) -> Integer- . compare(- a. pathWeight- , b. pathWeight));
- 		pending.add(source); 
- 		while ((source = pending.pollFirst()) != null) { 
- 			for (Entry<Node, Integer> edge : source.edges.entrySet()) { 
- 				Node dest = edge.getKey(); 
- 				int weight = source.pathWeight + edge.getValue(); 
- 				if (dest.path == null || weight < dest.pathWeight 
- 				                      || (weight == dest.pathWeight && source.path.length + 1 < dest.path.length)) { 
- 					if (dest.path != null) 
- 						pending.remove(dest); 
- 					dest. path = Arrays- . copyOf(- source. path- , source. path- . length + 1);
- 					dest.path[source.path.length] = dest; 
- 					dest.pathWeight = weight; 
- 					pending.add(dest); 
- 				} 
- 			} 
- 		} 
- 	} 
-   
- 	public String-  getPath (int-  endNo ) {
 
- 		Node node = this.nodes.get(endNo); 
- 		return (node == null || node.path == null ? "Unreachable" : 
- 		        Arrays- . stream(- node. path)- . map(- n  -> String- . valueOf(- n. no))- . collect(- Collectors. joining(" - "))
 
- 		        + " (distance: " + node.pathWeight + ")"); 
- 	} 
- } 
				aW1wb3J0IGphdmEudXRpbC5BcnJheXM7CmltcG9ydCBqYXZhLnV0aWwuSGFzaE1hcDsKaW1wb3J0IGphdmEudXRpbC5NYXA7CmltcG9ydCBqYXZhLnV0aWwuTWFwLkVudHJ5OwppbXBvcnQgamF2YS51dGlsLlRyZWVTZXQ7CmltcG9ydCBqYXZhLnV0aWwuc3RyZWFtLkNvbGxlY3RvcnM7CgpjbGFzcyBJZGVvbmUgewoJcHVibGljIHN0YXRpYyB2b2lkIG1haW4oU3RyaW5nW10gYXJncykgewoJCXRlc3QxKCk7CgkJdGVzdDIoKTsKCX0KCXB1YmxpYyBzdGF0aWMgdm9pZCB0ZXN0MSgpIHsKCQlHcmFwaCBncmFwaCA9IG5ldyBHcmFwaCgpOwoJCWdyYXBoLmFkZEVkZ2UoMCwgMSwgNCk7CgkJZ3JhcGguYWRkRWRnZSgwLCAyLCAzKTsKCQlncmFwaC5hZGRFZGdlKDEsIDIsIDEpOwoJCWdyYXBoLmFkZEVkZ2UoMSwgMywgMik7CgkJZ3JhcGguYWRkRWRnZSgyLCAzLCA0KTsKCQlncmFwaC5hZGRFZGdlKDMsIDQsIDIpOwoJCWdyYXBoLmFkZEVkZ2UoNCwgNSwgNik7CgkJZ3JhcGguc3RhcnRBdCgwKTsKCQlTeXN0ZW0ub3V0LnByaW50bG4oZ3JhcGguZ2V0UGF0aCg1KSk7Cgl9CglwdWJsaWMgc3RhdGljIHZvaWQgdGVzdDIoKSB7CgkJR3JhcGggZ3JhcGggPSBuZXcgR3JhcGgoKTsKCQlncmFwaC5hZGRFZGdlKDAsIDEsIDQpOwoJCWdyYXBoLmFkZEVkZ2UoMCwgMiwgMyk7CgkJZ3JhcGguYWRkRWRnZSgxLCAzLCAyKTsKCQlncmFwaC5hZGRFZGdlKDEsIDIsIDUpOwoJCWdyYXBoLmFkZEVkZ2UoMiwgMywgNyk7CgkJZ3JhcGguYWRkRWRnZSgzLCA0LCAyKTsKCQlncmFwaC5hZGRFZGdlKDQsIDAsIDQpOwoJCWdyYXBoLmFkZEVkZ2UoNCwgMSwgNCk7CgkJZ3JhcGguYWRkRWRnZSg0LCA1LCA2KTsKCQlncmFwaC5zdGFydEF0KDApOwoJCVN5c3RlbS5vdXQucHJpbnRsbihncmFwaC5nZXRQYXRoKDUpKTsKCX0KfQpmaW5hbCBjbGFzcyBHcmFwaCB7Cglwcml2YXRlIHN0YXRpYyBmaW5hbCBjbGFzcyBOb2RlIHsKCQlmaW5hbCBpbnQgbm87CgkJTWFwPE5vZGUsIEludGVnZXI+IGVkZ2VzID0gbmV3IEhhc2hNYXA8PigpOwoJCU5vZGVbXSBwYXRoOwoJCWludCBwYXRoV2VpZ2h0OwoJCU5vZGUoaW50IG5vKSB7CgkJCXRoaXMubm8gPSBubzsKCQl9Cgl9CgoJcHJpdmF0ZSBNYXA8SW50ZWdlciwgTm9kZT4gbm9kZXMgPSBuZXcgSGFzaE1hcDw+KCk7CgoJcHVibGljIHZvaWQgYWRkRWRnZShpbnQgc291cmNlTm8sIGludCBkZXN0aW5hdGlvbk5vLCBpbnQgd2VpZ2h0KSB7CgkJTm9kZSBzb3VyY2UgPSB0aGlzLm5vZGVzLmNvbXB1dGVJZkFic2VudChzb3VyY2VObywgTm9kZTo6bmV3KTsKCQlOb2RlIGRlc3QgPSB0aGlzLm5vZGVzLmNvbXB1dGVJZkFic2VudChkZXN0aW5hdGlvbk5vLCBOb2RlOjpuZXcpOwoJCXNvdXJjZS5lZGdlcy5wdXQoZGVzdCwgd2VpZ2h0KTsKCQlkZXN0LmVkZ2VzLnB1dChzb3VyY2UsIHdlaWdodCk7Cgl9CgoJcHVibGljIHZvaWQgc3RhcnRBdChpbnQgc3RhcnRObykgewoJCXRoaXMubm9kZXMudmFsdWVzKCkuZm9yRWFjaChuIC0+IG4ucGF0aCA9IG51bGwpOwoJCU5vZGUgc291cmNlID0gdGhpcy5ub2Rlcy5jb21wdXRlSWZBYnNlbnQoc3RhcnRObywgTm9kZTo6bmV3KTsKCQlzb3VyY2UucGF0aCA9IG5ldyBOb2RlW10geyBzb3VyY2UgfTsKCQlzb3VyY2UucGF0aFdlaWdodCA9IDA7CgkJVHJlZVNldDxOb2RlPiBwZW5kaW5nID0gbmV3IFRyZWVTZXQ8PigoYSwgYikgLT4gSW50ZWdlci5jb21wYXJlKGEucGF0aFdlaWdodCwgYi5wYXRoV2VpZ2h0KSk7CgkJcGVuZGluZy5hZGQoc291cmNlKTsKCQl3aGlsZSAoKHNvdXJjZSA9IHBlbmRpbmcucG9sbEZpcnN0KCkpICE9IG51bGwpIHsKCQkJZm9yIChFbnRyeTxOb2RlLCBJbnRlZ2VyPiBlZGdlIDogc291cmNlLmVkZ2VzLmVudHJ5U2V0KCkpIHsKCQkJCU5vZGUgZGVzdCA9IGVkZ2UuZ2V0S2V5KCk7CgkJCQlpbnQgd2VpZ2h0ID0gc291cmNlLnBhdGhXZWlnaHQgKyBlZGdlLmdldFZhbHVlKCk7CgkJCQlpZiAoZGVzdC5wYXRoID09IG51bGwgfHwgd2VpZ2h0IDwgZGVzdC5wYXRoV2VpZ2h0CgkJCQkgICAgICAgICAgICAgICAgICAgICAgfHwgKHdlaWdodCA9PSBkZXN0LnBhdGhXZWlnaHQgJiYgc291cmNlLnBhdGgubGVuZ3RoICsgMSA8IGRlc3QucGF0aC5sZW5ndGgpKSB7CgkJCQkJaWYgKGRlc3QucGF0aCAhPSBudWxsKQoJCQkJCQlwZW5kaW5nLnJlbW92ZShkZXN0KTsKCQkJCQlkZXN0LnBhdGggPSBBcnJheXMuY29weU9mKHNvdXJjZS5wYXRoLCBzb3VyY2UucGF0aC5sZW5ndGggKyAxKTsKCQkJCQlkZXN0LnBhdGhbc291cmNlLnBhdGgubGVuZ3RoXSA9IGRlc3Q7CgkJCQkJZGVzdC5wYXRoV2VpZ2h0ID0gd2VpZ2h0OwoJCQkJCXBlbmRpbmcuYWRkKGRlc3QpOwoJCQkJfQoJCQl9CgkJfQoJfQoKCXB1YmxpYyBTdHJpbmcgZ2V0UGF0aChpbnQgZW5kTm8pIHsKCQlOb2RlIG5vZGUgPSB0aGlzLm5vZGVzLmdldChlbmRObyk7CgkJcmV0dXJuIChub2RlID09IG51bGwgfHwgbm9kZS5wYXRoID09IG51bGwgPyAiVW5yZWFjaGFibGUiIDoKCQkgICAgICAgIEFycmF5cy5zdHJlYW0obm9kZS5wYXRoKS5tYXAobiAtPiBTdHJpbmcudmFsdWVPZihuLm5vKSkuY29sbGVjdChDb2xsZWN0b3JzLmpvaW5pbmcoIiAtICIpKQoJCSAgICAgICAgKyAiIChkaXN0YW5jZTogIiArIG5vZGUucGF0aFdlaWdodCArICIpIik7Cgl9Cn0=