/// <summary> /// Algorytm znajdujący drugą pod względem długości najkrótszą ścieżkę między a i b. /// Możliwe, że jej długość jest równa najkrótszej (jeśli są dwie najkrótsze ścieżki, /// algorytm zwróci jedną z nich). /// Wymagamy, aby na ścieżce nie było powtórzeń wierzchołków ani krawędzi. /// Można założyć, że a!=b oraz że w grafie nie występują pętle. /// </summary> /// <remarks> /// Wymagana złożoność to O(nD), gdzie D jest złożonością implementacji algorytmu Dijkstry w bibliotece Graph. /// </remarks> /// <param name="g"></param> /// <param name="path">null jeśli druga ścieżka nie istnieje, wpp ściezka jako ciąg krawędzi</param> /// <returns>null jeśli druga ścieżka nie istnieje, wpp długość tej ścieżki</returns> public static double?FindSecondSimpleShortestPath(this Graph g, int a, int b, out Edge[] path) { path = null; PathsInfo[] d, best = null; double min = Double.MaxValue; g.DijkstraShortestPaths(a, out d); if (d[b].Dist.IsNaN()) { return(null); } Edge[] firstpath = PathsInfo.ConstructPath(a, b, d); foreach (Edge e in firstpath) { g.DelEdge(e); g.DijkstraShortestPaths(a, out d); if (d[b].Dist < min) { min = d[b].Dist; best = d; } g.AddEdge(e); } if (min == Double.MaxValue) { return(null); } path = PathsInfo.ConstructPath(a, b, best); return(min); }
/// <summary> /// Algorytm znajdujący drugą pod względem długości najkrótszą ścieżkę między a i b. /// Możliwe, że jej długość jest równa najkrótszej (jeśli są dwie najkrótsze ścieżki, /// algorytm zwróci jedną z nich). /// Wymagamy, aby na ścieżce nie było powtórzeń wierzchołków ani krawędzi. /// Można założyć, że a!=b oraz że w grafie nie występują pętle. /// </summary> /// <remarks> /// Wymagana złożoność to O(nD), gdzie D jest złożonością implementacji algorytmu Dijkstry w bibliotece Graph. /// </remarks> /// <param name="g"></param> /// <param name="path">null jeśli druga ścieżka nie istnieje, wpp ściezka jako ciąg krawędzi</param> /// <returns>null jeśli druga ścieżka nie istnieje, wpp długość tej ścieżki</returns> public static double?FindSecondSimpleShortestPath(this Graph g, int a, int b, out Edge[] path) { path = null; PathsInfo[] bestPathInfo, tempPathInfo, secondBestPathInfo = null; double secondBest = double.PositiveInfinity; EdgesStack stack = new EdgesStack(); if (!g.DijkstraShortestPaths(a, out bestPathInfo)) { return(null); } int v = b; int pathCount = 0; while (bestPathInfo[v].Last != null) { stack.Put((Edge)bestPathInfo[v].Last); v = stack.Peek().From; pathCount++; } Edge deleted; while (!stack.Empty) { deleted = stack.Get(); g.DelEdge(deleted); g.DijkstraShortestPaths(a, out tempPathInfo); if (tempPathInfo[b].Dist < secondBest) { secondBestPathInfo = tempPathInfo; secondBest = tempPathInfo[b].Dist; } g.AddEdge(deleted); } List <Edge> pathList = new List <Edge>(); v = b; if (!double.IsPositiveInfinity(secondBest)) { while (secondBestPathInfo[v].Last != null) { pathList.Add((Edge)secondBestPathInfo[v].Last); v = pathList.Last().From; } pathList.Reverse(); path = pathList.ToArray(); } if (path == null) { return(null); } else { return(pathList.Sum(edge => edge.Weight)); } }
/// <summary> /// Algorytm znajdujący drugą pod względem długości najkrótszą ścieżkę między a i b. /// Możliwe, że jej długość jest równa najkrótszej (jeśli są dwie najkrótsze ścieżki, /// algorytm zwróci jedną z nich). /// Wymagamy, aby na ścieżce nie było powtórzeń wierzchołków ani krawędzi. /// Można założyć, że a!=b oraz że w grafie nie występują pętle. /// </summary> /// <remarks> /// Wymagana złożoność to O(nD), gdzie D jest złożonością implementacji algorytmu Dijkstry w bibliotece Graph. /// </remarks> /// <param name="g"></param> /// <param name="path">null jeśli druga ścieżka nie istnieje, wpp ściezka jako ciąg krawędzi</param> /// <returns>null jeśli druga ścieżka nie istnieje, wpp długość tej ścieżki</returns> public static double?FindSecondSimpleShortestPath(this Graph g, int a, int b, out Edge[] path) { PathsInfo[] pi; PathsInfo[] pi2; Graph G = g.Clone(); G.DijkstraShortestPaths(a, out pi); if (double.IsNaN(pi[b].Dist)) { path = null; return(null); } Edge[] firstPath = PathsInfo.ConstructPath(a, b, pi); double secondShortest = double.PositiveInfinity; path = null; for (int i = firstPath.Length - 1; i >= 0; i--) { G.DelEdge(firstPath[i]); G.DijkstraShortestPaths(a, out pi2); if (double.IsNaN(pi2[b].Dist)) { continue; } if (pi2[b].Dist < secondShortest) { secondShortest = pi2[b].Dist; path = PathsInfo.ConstructPath(a, b, pi2); } G.AddEdge(firstPath[i]); } if (secondShortest == double.PositiveInfinity) { return(null); } return(secondShortest); }
/// <summary> /// Algorytm znajdujący drugą pod względem długości najkrótszą ścieżkę między a i b. /// Możliwe, że jej długość jest równa najkrótszej (jeśli są dwie najkrótsze ścieżki, /// algorytm zwróci jedną z nich). /// Wymagamy, aby na ścieżce nie było powtórzeń wierzchołków ani krawędzi. /// Można założyć, że a!=b oraz że w grafie nie występują pętle. /// </summary> /// <remarks> /// Wymagana złożoność to O(nD), gdzie D jest złożonością implementacji algorytmu Dijkstry w bibliotece Graph. /// </remarks> /// <param name="g"></param> /// <param name="path">null jeśli druga ścieżka nie istnieje, wpp ściezka jako ciąg krawędzi</param> /// <returns>null jeśli druga ścieżka nie istnieje, wpp długość tej ścieżki</returns> public static double?FindSecondSimpleShortestPath(this Graph g, int a, int b, out Edge[] path) { PathsInfo[] d; g.DijkstraShortestPaths(a, out d); Edge[] shortestPath = PathsInfo.ConstructPath(a, b, d); if (shortestPath == null) { path = null; return(null); } double minDist = double.MaxValue; bool changed = false; Edge[] temp = null; foreach (Edge e in shortestPath) { PathsInfo[] dT; Graph tG = g.Clone(); tG.DelEdge(e); tG.DijkstraShortestPaths(a, out dT); Edge[] secondShortest = PathsInfo.ConstructPath(a, b, dT); if (dT[b].Dist <= minDist) { changed = true; minDist = dT[b].Dist; temp = PathsInfo.ConstructPath(a, b, dT); } } if (!changed) { path = null; return(null); } path = temp; return(minDist); }