// Find the route with matching last station name and extend with new station name.
        public List <Route> SpawnMatchedRoute(List <Route> possibleRoutes, string prevStationName, Station stationToAdd, int duration)
        {
            List <Route> newRoutes = new List <Route>();

            foreach (Route route in possibleRoutes)
            {
                if (route.LastStation.Station.StationName == prevStationName)
                {
                    Route updatedRoute = (Route)route.Clone();
                    updatedRoute.AddStationToRoute(stationToAdd);
                    updatedRoute.AddTotalDuration(duration);
                    newRoutes.Add(updatedRoute);
                }
            }

            return(newRoutes);
        }
        public List <Route> FindKShortestPath(string sourceStationName, string destStationName, int k)
        {
            List <Route> kRoutes = new List <Route>();

            Queue <Station>  stationQueue       = new Queue <Station>();
            HashSet <string> visitedStationName = new HashSet <string>();
            Station          curStation         = Stations[sourceStationName];

            stationQueue.Enqueue(curStation);

            List <Route> possibleRoutes = new List <Route>();
            Route        startRoute     = new Route();

            startRoute.AddStationToRoute(curStation);
            possibleRoutes.Add(startRoute);
            visitedStationName.Add(curStation.StationName);
            bool foundKRoutes = false;

            while (stationQueue.Count > 0 && !foundKRoutes)
            {
                curStation = stationQueue.Dequeue();
                List <Route> updatedRoutes = new List <Route>();

                foreach (StationEdge stationEdge in curStation.ConnectedStations)
                {
                    Station connectedStation = stationEdge.Station;

                    //valid route found.
                    if (connectedStation.StationName == destStationName && kRoutes.Count < k)
                    {
                        List <Route> validRoutes         = SpawnValidRoute(possibleRoutes, curStation.StationName, connectedStation, stationEdge.Duration);
                        int          availableRouteSlots = k - kRoutes.Count < validRoutes.Count ? k - kRoutes.Count : validRoutes.Count;
                        for (int i = 0; i < availableRouteSlots; i++)
                        {
                            kRoutes.Add(validRoutes[i]);
                            possibleRoutes.Remove(validRoutes[i]);
                        }

                        if (kRoutes.Count >= k)
                        {
                            foundKRoutes = true;
                            break;
                        }
                        continue;
                    }

                    if (!visitedStationName.Contains(connectedStation.StationName))
                    {
                        visitedStationName.Add(curStation.StationName);
                        stationQueue.Enqueue(connectedStation);
                        updatedRoutes.AddRange(SpawnMatchedRoute(possibleRoutes, curStation.StationName, connectedStation, stationEdge.Duration));
                    }
                }

                if (updatedRoutes.Count > 0)
                {
                    updatedRoutes.AddRange(SpawnMismatchedRoute(possibleRoutes, curStation.StationName));
                    possibleRoutes = updatedRoutes;
                }
            }

            kRoutes = kRoutes.OrderBy(route => route.TotalDuration).ToList();
            return(kRoutes);
        }