public static DirectedWeightedGraph GetGraph(TextReader reader, bool makeUndirected) { if (reader == null) throw new ArgumentNullException("reader"); var graph = new DirectedWeightedGraph(); reader.ReadLine(); while (true) { string row = reader.ReadLine(); if (row == null) { break; } var parts = row.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); var numbers = parts.Select(x => int.Parse(x, CultureInfo.InvariantCulture)).ToArray(); var node1 = numbers[0] - 1; var node2 = numbers[1] - 1; var weight = numbers[2]; graph.AddEdge(node1, node2, weight); if (makeUndirected) { graph.AddEdge(node2, node1, weight); } } return graph; }
public void Run() { using (var reader = new StreamReader("dijkstraData.txt")) using (var writer = new StreamWriter("output.txt")) { var graph = new DirectedWeightedGraph(); while (true) { string row = reader.ReadLine(); if (row == null) { break; } var parts = row.Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries); var from = int.Parse(parts[0], CultureInfo.InvariantCulture) - 1; foreach (var part in parts.Skip(1)) { var tuple = part.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var to = int.Parse(tuple[0], CultureInfo.InvariantCulture) - 1; var weight = int.Parse(tuple[1], CultureInfo.InvariantCulture); graph.AddEdge(from, to, weight); } } var vertices = new[] { 6, 36, 58, 81, 98, 114, 132, 164, 187, 196 }; var distances = Dijkstra.Find(graph, 0).ToArray(); var result = string.Join(",", vertices.Select(v => distances[v])); writer.WriteLine(result); } }
public static IEnumerable<int?> Find(DirectedWeightedGraph graph, int source) { var dist = new int?[graph.NodesCount]; dist[source] = 0; var closestNodes = new PriorityQueue<int, int>(dist.Select((d, i) => new KeyValuePair<int, int>(i, d.GetValueOrDefault(int.MaxValue)))); var exploredNodes = new HashSet<int>(); while (closestNodes.Count != 0) { var node = closestNodes.ExtractHighestPriorityElement(); exploredNodes.Add(node); foreach (var edge in graph.GetEdges(node).Where(e => !exploredNodes.Contains(e.EndNode))) { if (dist[node] != null) { var alt = dist[node].Value + edge.Weight; if (alt < dist[edge.EndNode].GetValueOrDefault(int.MaxValue)) { dist[edge.EndNode] = alt; closestNodes.ChangePriority(edge.EndNode, alt); } } } } return dist; }
public static IReadOnlyList<int?> GetShortestPaths(DirectedWeightedGraph graph, int source) { int n = graph.NodesCount; var dist = new int?[n]; dist[source] = 0; for (int i = 0; i < dist.Length; i++) { if (i != source) { dist[i] = null; } } var edges = graph.GetEdges().ToArray(); for (int i = 0; i < n + 1; i++) { bool changed = false; foreach (var edge in edges) { if (dist[edge.StartNode] != null && dist[edge.StartNode] + edge.Weight < dist[edge.EndNode].GetValueOrDefault(int.MaxValue)) { dist[edge.EndNode] = dist[edge.StartNode] + edge.Weight; changed = true; } } if (!changed) return dist; } return null; }
public static int GetMinimumSpanningTreeLength(DirectedWeightedGraph graph) { int length = 0; var dist = new int[graph.NodesCount]; const int StartNode = 0; dist[StartNode] = 0; for (int i = 0; i < dist.Length; i++) { if (i != StartNode) { dist[i] = int.MaxValue; } } var closestNodes = new PriorityQueue<int, int>(dist.Select((d, i) => new KeyValuePair<int, int>(i, d))); var exploredNodes = new HashSet<int>(); while (exploredNodes.Count != graph.NodesCount) { var node = closestNodes.ExtractHighestPriorityElement(); length += dist[node]; exploredNodes.Add(node); foreach (var edge in graph.GetEdges(node).Where(e => !exploredNodes.Contains(e.EndNode))) { var alt = edge.Weight; if (alt < dist[edge.EndNode]) { dist[edge.EndNode] = alt; closestNodes.ChangePriority(edge.EndNode, alt); } } } return length; }
public void FindTest() { var graph = new DirectedWeightedGraph(); graph.AddEdge(0, 1, 1); graph.AddEdge(0, 2, 4); graph.AddEdge(1, 2, 2); graph.AddEdge(1, 3, 6); graph.AddEdge(2, 3, 3); var distances = Dijkstra.Find(graph, 0); distances.Should().Equal(new[] { 0, 1, 3, 6 }); }
public void TestCycles() { var graph = new DirectedWeightedGraph(); graph.AddEdge(0, 1, -1); graph.AddEdge(1, 0, -1); graph.AddEdge(0, 2, -1); graph.AddEdge(2, 0, -1); graph.AddEdge(1, 2, -1); graph.AddEdge(2, 1, -1); var distances = FloydWarshall.GetShortestPaths(graph); }
public void GetShortestPathsTest2() { var graph = new DirectedWeightedGraph(); graph.AddEdge(0, 1, 1); graph.AddEdge(1, 2, 2); graph.AddEdge(2, 3, 3); graph.AddEdge(3, 1, -6); graph.AddEdge(4, 3, 7); var distances = Johnson.GetShortestPaths(graph); distances.Should().BeNull("Graph contains a negative-weight cycle"); }
public static int?[,] GetShortestPaths(DirectedWeightedGraph graph) { int n = graph.NodesCount; var distances = new int?[n, n]; for (int i = 0; i < n; i++) { distances[i, i] = 0; } foreach (var edge in graph.GetEdges()) { distances[edge.StartNode, edge.EndNode] = edge.Weight; } for (int k = 0; k < n; k++) for (int i = 0; i < n; i++) for (int j = 0; j < n; j++) { int? prevDistance = distances[i, j]; int? newDistance = distances[i, k] + distances[k, j]; if (prevDistance == null) { distances[i, j] = newDistance; } else if (newDistance == null) { distances[i, j] = prevDistance; } else { distances[i, j] = Math.Min(prevDistance.GetValueOrDefault(), newDistance.GetValueOrDefault()); } } for (int i = 0; i < n; i++) { if (distances[i, i] < 0) return null; } return distances; }
public void GetMinimumSpanningTreeLengthTest() { var graph = new DirectedWeightedGraph(); graph.AddEdge(0, 1, 1); graph.AddEdge(0, 2, 4); graph.AddEdge(0, 3, 3); graph.AddEdge(1, 0, 1); graph.AddEdge(1, 3, 2); graph.AddEdge(2, 0, 4); graph.AddEdge(2, 3, 5); graph.AddEdge(3, 0, 3); graph.AddEdge(3, 1, 2); graph.AddEdge(3, 2, 5); var mstLength = PrimsAlgorithm.GetMinimumSpanningTreeLength(graph); mstLength.Should().Be(7); }
public void GetShortestPathsTest() { var graph = new DirectedWeightedGraph(); graph.AddEdge(0, 1, -2); graph.AddEdge(1, 2, -1); graph.AddEdge(2, 0, 4); graph.AddEdge(2, 3, 2); graph.AddEdge(2, 3, 2); graph.AddEdge(2, 4, -3); graph.AddEdge(2, 4, -3); graph.AddEdge(5, 3, 1); graph.AddEdge(5, 4, -4); var distances = Johnson.GetShortestPaths(graph); var elements = new int?[,] { { 0, -2, -3, -1, -6, null }, { 3, 0, -1, 1, -4, null }, { 4, 2, 0, 2, -3, null }, { null, null, null, 0, null, null }, { null, null, null, null, 0, null }, { null, null, null, 1, -4, 0 } }; distances.Should().BeEquivalentTo(elements); }
public void GetMaxSpacingTest() { var graph = new DirectedWeightedGraph(); graph.AddEdge(0, 1, 1); graph.AddEdge(0, 2, 6); graph.AddEdge(0, 3, 7); graph.AddEdge(1, 0, 1); graph.AddEdge(1, 2, 8); graph.AddEdge(1, 3, 5); graph.AddEdge(2, 0, 6); graph.AddEdge(2, 1, 8); graph.AddEdge(2, 3, 2); graph.AddEdge(3, 0, 7); graph.AddEdge(3, 1, 5); graph.AddEdge(3, 2, 2); Clustering.GetMaxSpacing(graph, 4).Should().Be(1); Clustering.GetMaxSpacing(graph, 3).Should().Be(2); Clustering.GetMaxSpacing(graph, 2).Should().Be(5); }
public static int GetMaxSpacing(DirectedWeightedGraph graph, int clusterCount) { int currentClusterCount = graph.NodesCount; var unionFind = new UnionFind(currentClusterCount); var edges = new PriorityQueue<WeightedEdge, int>(graph.GetEdges().Select(e => new KeyValuePair<WeightedEdge, int>(e, e.Weight))); while (currentClusterCount >= clusterCount) { var edge = edges.ExtractHighestPriorityElement(); var cluster1 = unionFind.Find(edge.StartNode); var cluster2 = unionFind.Find(edge.EndNode); if (cluster1 != cluster2) { if (currentClusterCount == clusterCount) { return edge.Weight; } unionFind.Union(cluster1, cluster2); currentClusterCount--; } } return 0; }