public State makeExclude(int x, int y, State state)                                              //O(n^2)
        {
            State excludeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2)

            excludeState.setPoint(x, y, double.PositiveInfinity);                                        //make chosen point infinity
            reduceMatrix(excludeState);                                                                  //O(n^2)
            excludeState.setEdges(state.getEdges());                                                     //initialize excludeStates edges
            return(excludeState);
        }
 public bool isDictionaryFilled(State state) //O(n)
 {                                           //returns whether or not the all of the edges have been added
     for (int i = 0; i < state.getEdges().Count; i++)
     {
         if (state.getEdge(i) == -1)
         {
             return(false); //if one hasn't been added, then it isn't full
         }
     }
     return(true);
 }
        public void checkCycles(State state, int i, int j) //O(n)
        {
            Dictionary <int, int> edges = new Dictionary <int, int>(state.getEdges());

            if (getDictionarySize(edges) == edges.Count) //if the dictionary is full, stop
            {
                return;
            }

            int[] entered = new int[edges.Count];
            int[] exited  = new int[edges.Count];
            for (int x = 0; x < entered.Length; x++) //O(n)
            {
                entered[x] = -1;
            }
            for (int x = 0; x < edges.Count; x++) //O(n)
            {
                exited[x] = edges[x];
                if (exited[x] != -1)
                {
                    entered[exited[x]] = x;
                }
            }

            //the two loops above "flip" the arrays with value and index, e.g. if
            //entered contained [0]=2, [1]=0, [2]=1
            //exited will now contain [0]=1, [1]=2, [2]=0

            entered[j] = i;
            exited[i]  = j;

            int start = i;
            int end   = j;

            while (exited[end] != -1) //O(n)
            {
                end = exited[end];
            }
            while (entered[start] != -1)//O(n)
            {
                start = entered[start];
            }
            if (getDictionarySize(edges) != edges.Count - 1) //if there is only one point left to fill,
            {                                                //this will think there is a cycle, so make
                while (start != j)                           //O(n)                      make sure there isn't one element left
                {
                    state.setPoint(end, start, double.PositiveInfinity);
                    state.setPoint(j, start, double.PositiveInfinity);
                    start = exited[start];
                }
            }
        }
        public State makeInclude(int x, int y, State state)                                              //O(n^2)
        {
            State includeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2)

            includeState.setPoint(y, x, double.PositiveInfinity);                                        //set the "opposite point to infinity"
            for (int j = 0; j < includeState.getMap().GetLength(1); j++)                                 //set the row to infinity, O(n)
            {
                includeState.setPoint(x, j, double.PositiveInfinity);
            }
            for (int i = 0; i < includeState.getMap().GetLength(0); i++) //set the column to infinity, O(n)
            {
                includeState.setPoint(i, y, double.PositiveInfinity);
            }
            reduceMatrix(includeState);              //O(n^2)
            includeState.setEdges(state.getEdges()); //initialize includeState's dictionary of edges
            return(includeState);
        }
 //O(n^2)
 public State makeInclude(int x, int y, State state)
 {
     State includeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2)
     includeState.setPoint(y, x, double.PositiveInfinity); //set the "opposite point to infinity"
     for (int j = 0; j < includeState.getMap().GetLength(1); j++) //set the row to infinity, O(n)
     {
         includeState.setPoint(x, j, double.PositiveInfinity);
     }
     for (int i = 0; i < includeState.getMap().GetLength(0); i++) //set the column to infinity, O(n)
     {
         includeState.setPoint(i, y, double.PositiveInfinity);
     }
     reduceMatrix(includeState); //O(n^2)
     includeState.setEdges(state.getEdges()); //initialize includeState's dictionary of edges
     return includeState;
 }
 //O(n^2)
 public State makeExclude(int x, int y, State state)
 {
     State excludeState = new State(copyMatrix(state.getMap()), state.getLB(), state.getEdges()); //O(n^2)
     excludeState.setPoint(x, y, double.PositiveInfinity); //make chosen point infinity
     reduceMatrix(excludeState); //O(n^2)
     excludeState.setEdges(state.getEdges()); //initialize excludeStates edges
     return excludeState;
 }
 //O(n)
 public bool isDictionaryFilled(State state)
 {
     //returns whether or not the all of the edges have been added
     for (int i = 0; i < state.getEdges().Count; i++)
     {
         if (state.getEdge(i) == -1)
             return false; //if one hasn't been added, then it isn't full
     }
     return true;
 }
        //O(n)
        public void checkCycles(State state, int i, int j)
        {
            Dictionary<int, int> edges = new Dictionary<int, int>(state.getEdges());
            if (getDictionarySize(edges) == edges.Count) //if the dictionary is full, stop
                return;

            int[] entered = new int[edges.Count];
            int[] exited = new int[edges.Count];
            for (int x = 0; x < entered.Length; x++) //O(n)
                entered[x] = -1;
            for (int x = 0; x < edges.Count; x++) //O(n)
            {
                exited[x] = edges[x];
                if (exited[x] != -1)
                    entered[exited[x]] = x;
            }

            //the two loops above "flip" the arrays with value and index, e.g. if
            //entered contained [0]=2, [1]=0, [2]=1
            //exited will now contain [0]=1, [1]=2, [2]=0

            entered[j] = i;
            exited[i] = j;

            int start = i;
            int end = j;
            while (exited[end] != -1) //O(n)
                end = exited[end];
            while (entered[start] != -1)//O(n)
                start = entered[start];
            if (getDictionarySize(edges) != edges.Count - 1) //if there is only one point left to fill,
            {                                                //this will think there is a cycle, so make
                while (start != j) //O(n)                      make sure there isn't one element left
                {
                    state.setPoint(end, start, double.PositiveInfinity);
                    state.setPoint(j, start, double.PositiveInfinity);
                    start = exited[start];
                }
            }
        }
        Stopwatch timer;            //global timer
        public void branchAndBoundSolve()
        {
            initialState = new State(new Double[Cities.Length, Cities.Length]);
            timer        = new Stopwatch();
            timer.Start();
            for (int i = 0; i < Cities.Length; i++) //O(n^2), initialize initialStates map
            {
                for (int x = 0; x < Cities.Length; x++)
                {
                    initialState.setPoint(i, x, Cities[i].costToGetTo(Cities[x]));
                    if (initialState.getPoint(i, x) == 0)
                    {
                        initialState.setPoint(i, x, double.PositiveInfinity);
                    }
                }
            }
            initialState.initializeEdges();     //initializeEdges initializes the state's dictionary
                                                //with key 0 to n (# of cities), value -> -1
            reduceMatrix(initialState);         //reduce the matrix to find lower bound

            queue = new IntervalHeap <State>(); //this is a global queue
            BSSF  = greedy();                   //find initial best solution so far, O(n^4)
            Console.WriteLine("BSSF: " + BSSF);
            findGreatestDiff(initialState);     //exclude minus include, O(n^3)
            TimeSpan ts = timer.Elapsed;
            bool     terminatedEarly = false;   //boolean to keep track if we stopped after 30 seconds
            int      maxStates       = 0;       //keeps track of the maximum amount of states in the queue at one point
            int      totalSeconds    = 0;

            while (queue.Count != 0)         //O(2^n * n^3), because each time you expand a node, it expands it 2 times, exponentially
            {                                //where n is the number of cities
                if (queue.Count > maxStates) //if maxStates needs to be updated, update it
                {
                    maxStates = queue.Count;
                }
                ts = timer.Elapsed;

                State min = queue.DeleteMin();
                if (totalSeconds < ts.Seconds)
                {
                    totalSeconds = ts.Seconds;
                    Console.WriteLine("seconds: " + totalSeconds);
                }

                if (min.getLB() < BSSF)    //if the min popped off the queue has a lowerbound less than
                {
                    findGreatestDiff(min); //the BSSF, expand it, otherwise, prune it. -> O(n^3)
                }
                else
                {//all of the lowerbounds are worse than the BSSF, break!
                    break;
                }
            }
            if (!terminatedEarly)//if it solved the problem in less than 30 seconds
            {
                int city = 0;
                for (int i = 0; i < bestState.getEdges().Count; i++) //O(n)
                {
                    if (i == 0)                                      //outputting a map into the Route list
                    {
                        Route.Add(Cities[i]);
                        city = bestState.getEdge(i);
                    }
                    else
                    {
                        Route.Add(Cities[city]);
                        city = bestState.getEdge(city);
                    }
                }
                bssf = new TSPSolution(Route);
                // update the cost of the tour.
                Program.MainForm.tbCostOfTour.Text  = " " + bssf.costOfRoute();
                Program.MainForm.tbElapsedTime.Text = ts.TotalSeconds.ToString();
                // do a refresh.
                Program.MainForm.Invalidate();
            }
        }