private static bool DFS
        (
            WeightedDiGraph G,
            Arrow current,
            List <Arrow> resultPath,
            int sink
        )
        {
            if (current.GetEnd() == sink)
            {
                resultPath.Add(new Arrow(current));
                return(true);
            }

            List <Arrow> outcomingArrows = G.GetArrowsFrom(current.GetEnd());

            foreach (Arrow a in outcomingArrows)
            {
                if (DFS(G, a, resultPath, sink))
                {
                    resultPath.Add(current);
                    return(true);
                }
            }

            return(false);
        }
        public static List <Arrow> GetCriticalPath(WeightedDiGraph G)
        {
            WeightedDiGraph subgraph        = new WeightedDiGraph(GetCriticalProcesses(G));
            List <Arrow>    outcomingArrows = subgraph.GetArrowsFrom(Sorter.GetTopologicalMin(G));
            List <Arrow>    resultPath      = new List <Arrow>();

            foreach (Arrow a in outcomingArrows)
            {
                DFS(subgraph, a, resultPath, Sorter.GetTopologicalMax(G));
            }

            resultPath.Reverse();
            return(resultPath);
        }
        private static void DFS
        (
            int v,
            WeightedDiGraph G,
            Dictionary <int, bool> used,
            List <int> result
        )
        {
            used[v] = true;
            List <Arrow> outcomingArrows = G.GetArrowsFrom(v);

            foreach (Arrow a in outcomingArrows)
            {
                if (!used[a.GetEnd()])
                {
                    DFS(a.GetEnd(), G, used, result);
                }
            }

            result.Add(v);
        }
        public static List <int> TopologicalSort(WeightedDiGraph G)
        {
            List <int>             vertices = G.GetVertices();
            Dictionary <int, bool> used     = new Dictionary <int, bool>();
            List <int>             result   = new List <int>();

            foreach (int v in vertices)
            {
                used[v] = false;
            }

            result.Clear();
            foreach (int v in vertices)
            {
                if (!used[v])
                {
                    DFS(v, G, used, result);
                }
            }
            result.Reverse();

            return(result);
        }
        public static List <Arrow> GetCriticalProcesses(WeightedDiGraph G)
        {
            Dictionary <int, double> earliestStart = new Dictionary <int, double>();
            List <int> vertices = G.GetVerticesSorted();

            int source = vertices.Min();

            earliestStart[source] = 0;

            foreach (int v in vertices)
            {
                earliestStart[v] = 0;
            }

            foreach (int v in vertices)
            {
                List <Arrow> incomingArrows = G.GetArrowsTo(v);

                foreach (Arrow a in incomingArrows)
                {
                    double current = earliestStart[a.GetBegin()] + a.GetWeight();

                    if (current > earliestStart[a.GetEnd()])
                    {
                        earliestStart[a.GetEnd()] = current;
                    }
                }
            }


            int sinkVertex = vertices[vertices.Count() - 1];
            Dictionary <int, double> latestStart = new Dictionary <int, double>();

            foreach (int v in vertices)
            {
                latestStart[v] = double.MaxValue;
            }
            latestStart[sinkVertex] = earliestStart[sinkVertex];

            vertices.Reverse();

            foreach (int v in vertices)
            {
                List <Arrow> outcomingArrows = G.GetArrowsFrom(v);

                foreach (Arrow a in outcomingArrows)
                {
                    double current = earliestStart[a.GetEnd()] - a.GetWeight();

                    if (current < latestStart[v])
                    {
                        latestStart[v] = current;
                    }
                }
            }


            List <Arrow> criticalProcesses = new List <Arrow>();

            List <Arrow> arrows = G.GetArrows();

            foreach (Arrow a in arrows)
            {
                if
                (
                    earliestStart[a.GetBegin()] == latestStart[a.GetBegin()] &&
                    earliestStart[a.GetEnd()] == latestStart[a.GetEnd()] &&
                    earliestStart[a.GetEnd()] - earliestStart[a.GetBegin()] == a.GetWeight() &&
                    latestStart[a.GetEnd()] - latestStart[a.GetBegin()] == a.GetWeight()
                )
                {
                    criticalProcesses.Add(new Arrow(a));
                }
            }

            return(criticalProcesses);
        }
        public static int GetTopologicalMax(WeightedDiGraph G)
        {
            List <int> sorted = TopologicalSort(G);

            return(sorted[sorted.Count() - 1]);
        }
 public static int GetTopologicalMin(WeightedDiGraph G)
 {
     return(TopologicalSort(G)[0]);
 }