/// <summary> /// Computes all shortest distance between any vertices in a given graph. /// </summary> /// <param name="adjacence_matrix">Square adjacence matrix. The main diagonal /// is expected to consist of zeros, any non-existing edges should be marked /// positive infinity.</param> /// <returns>Two matrices D and P, where D[u,v] holds the distance of the shortest /// path between u and v, and P[u,v] holds the shortcut vertex on the way from /// u to v.</returns> public static ArrayMatrix[] Floyd(ArrayMatrix adjacence_matrix) { if (!adjacence_matrix.IsSquare()) throw new ArgumentException("Expected square matrix."); else if (!adjacence_matrix.IsReal()) throw new ArgumentException("Adjacence matrices are expected to be real."); var n = adjacence_matrix.RowCount; var D = adjacence_matrix.Clone(); // distance matrix var P = new ArrayMatrix(n); double buf; for (var k = 1; k <= n; k++) for (var i = 1; i <= n; i++) for (var j = 1; j <= n; j++) { buf = D[i, k].Real + D[k, j].Real; if (buf < D[i, j].Real) { D[i, j].Real = buf; P[i, j].Real = k; } } return new ArrayMatrix[] {D, P}; }
/// <summary> /// Returns the shortest path between two given vertices i and j as /// int array. /// </summary> /// <param name="P">Path matrix as returned from Floyd().</param> /// <param name="i">One-based index of start vertex.</param> /// <param name="j">One-based index of end vertex.</param> /// <returns></returns> public static ArrayList FloydPath(ArrayMatrix P, int i, int j) { if (!P.IsSquare()) throw new ArgumentException("Path matrix must be square."); else if (!P.IsReal()) throw new ArgumentException("Adjacence matrices are expected to be real."); var path = new ArrayList(); path.Add(i); //int borderliner = 0; //int n = P.Size()[0] + 1; // shortest path cannot have more than n vertices! while (P[i, j] != 0) { i = Convert.ToInt32(P[i, j]); path.Add(i); //borderliner++; //if (borderliner == n) // throw new FormatException("P was not a Floyd path matrix."); } path.Add(j); return path; }
/// <summary> /// Performs depth-first search for a graph given by its adjacence matrix. /// </summary> /// <param name="adjacence_matrix">A[i,j] = 0 or +infty, if there is no edge from i to j; any non-zero value otherwise.</param> /// <param name="root">The vertex to begin the search.</param> /// <returns>Adjacence matrix of the computed spanning tree.</returns> public static ArrayMatrix DFS(ArrayMatrix adjacence_matrix, int root) { if (!adjacence_matrix.IsSquare()) throw new ArgumentException("Adjacence matrices are expected to be square."); else if (!adjacence_matrix.IsReal()) throw new ArgumentException("Adjacence matrices are expected to be real."); var n = adjacence_matrix.RowCount; if (root < 1 || root > n) throw new ArgumentException("Root must be a vertex of the graph, e.i. in {1, ..., n}."); var spanTree = new ArrayMatrix(n); var marked = new bool[n + 1]; var todo = new Stack(); todo.Push(root); marked[root] = true; // adajacence lists for each vertex var A = new ArrayList[n + 1]; for (var i = 1; i <= n; i++) { A[i] = new ArrayList(); for (var j = 1; j <= n; j++) if (adjacence_matrix[i, j].Real != 0 && adjacence_matrix[i, j].Imag != double.PositiveInfinity) A[i].Add(j); } int v, w; while (todo.Count > 0) { v = (int) todo.Peek(); if (A[v].Count > 0) { w = (int) A[v][0]; if (!marked[w]) { marked[w] = true; // mark w spanTree[v, w].Real = 1; // mark vw todo.Push(w); // one more to search } A[v].RemoveAt(0); } else todo.Pop(); } return spanTree; }