/*
         * For the unweighted graph, <name>:
         *
         * 1. The number of nodes is <name>Nodes.
         * 2. The number of edges is <name>Edges.
         * 3. An edge exists between <name>From[i] to <name>To[i].
         *
         */
        static int findShortest(int graphNodes, int[] graphFrom, int[] graphTo, long[] ids, long val)
        {
            List <int> maxInts = new List <int>();
            int        minDist = int.MaxValue;
            GraphAPI   gapi    = new GraphAPI(graphNodes, ids);

            for (int i = 0; i < graphFrom.Length; i++)
            {
                gapi.AddEdge(graphFrom[i], graphTo[i]);
            }

            List <int> impNodes = new List <int>();

            for (int i = 0; i < graphNodes; i++)
            {
                if (ids[i] == val)
                {
                    impNodes.Add(i);
                }
            }

            for (int i = 0; i < impNodes.Count; i++)
            {
                BreadthFirstSearch bfs = new BreadthFirstSearch(gapi, gapi.S, impNodes[i], val);
                minDist = Math.Min(minDist, bfs.minDist);

                //List<int> innerValues = new List<int>();
                //for (int j = 0; j < graphNodes; j++)
                //{
                //    if (ids[j] == val)
                //    {
                //        innerValues.Add(dfs.DistTo[j]);
                //    }
                //}

                //innerValues.Sort();

                //if (innerValues.Count > 1)
                //{
                //    maxInts.Add(innerValues[0] + innerValues[1]);
                //}
            }

            //maxInts.Sort();

            return(minDist != int.MaxValue ? minDist : -1);
        }
        static long roadsAndLibraries(int n, long c_lib, long c_road, int[][] cities)
        {
            GraphAPI gapi = new GraphAPI(n);

            for (int i = 0; i < cities.Length; i++)
            {
                gapi.AddEdge(cities[i][0], cities[i][1]);
            }

            ConnectedComponents bfs = new ConnectedComponents(gapi, n);
            long result             = ((c_road * bfs.RoadCount()) + (bfs.LibraryCount() * c_lib));

            if (c_lib * n < result)
            {
                result = c_lib * n;
            }

            return(result);
        }
        /*Suppose that we have n groups, of sizes a1 to an. Except when n is smallish, the following formula for the number N of ways
         * to choose a pair of people from different groups is more efficient:
         * N=((a1+⋯+an)^2 − (a1^2 +⋯+ an^2)) / 2.
         * To see that the formula does the job, expand (a1+⋯+an)2.*/
        static long journeyToMoon(int n, int[][] astronaut)
        {
            GraphAPI gapi = new GraphAPI(n);

            for (int i = 0; i < astronaut.Length; i++)
            {
                gapi.AddEdge(astronaut[i][0], astronaut[i][1]);
            }

            ConnectedComponents bfs     = new ConnectedComponents(gapi, n);
            IList <long>        IdCount = new List <long>();

            IdCount.Add(1);
            Array.Sort(bfs.Id);
            for (int k = 0; k < n - 1; k++)
            {
                if (bfs.Id[k] == bfs.Id[k + 1])
                {
                    ++IdCount[IdCount.Count - 1];
                    continue;
                }

                IdCount.Add(1);
            }

            long SumSquare = 0;

            for (int i = 0; i < IdCount.Count; i++)
            {
                SumSquare += IdCount[i];
            }

            SumSquare = (long)Math.Pow(SumSquare, 2);
            long SquareSum = 0;

            for (int i = 0; i < IdCount.Count; i++)
            {
                SquareSum += (long)Math.Pow(IdCount[i], 2);
            }

            return((SumSquare - SquareSum) / 2);
        }
        static int maxRegion(int[][] grid, int nodeCount)
        {
            GraphAPI gapi = new GraphAPI(nodeCount);
            Dictionary <string, int> dict = new Dictionary <string, int>();
            int nodeNumber = 1;

            for (int i = 0; i < grid.Length; i++)
            {
                for (int j = 0; j < grid[i].Length; j++)
                {
                    string key = i + "|" + j;
                    dict.Add(key, nodeNumber);
                    nodeNumber++;
                }
            }


            for (int i = 0; i < grid.Length; i++)
            {
                for (int j = 0; j < grid[i].Length; j++)
                {
                    if (grid[i][j] == 1)
                    {
                        var keyOuter = i + "|" + j;
                        var from     = dict[keyOuter];

                        if (j > 0 && i < grid.Length - 1 && grid[i + 1][j - 1] == 1)
                        {
                            var keyInner = (i + 1) + "|" + (j - 1);
                            var to       = dict[keyInner];
                            gapi.AddEdge(from, to);
                        }

                        if (j < grid[i].Length - 1 && grid[i][j + 1] == 1)
                        {
                            var keyInner = (i) + "|" + (j + 1);
                            var to       = dict[keyInner];
                            gapi.AddEdge(from, to);
                        }

                        if (i < grid.Length - 1 && grid[i + 1][j] == 1)
                        {
                            var keyInner = (i + 1) + "|" + j;
                            var to       = dict[keyInner];
                            gapi.AddEdge(from, to);
                        }

                        if (i < grid.Length - 1 && j < grid[i].Length - 1 && grid[i + 1][j + 1] == 1)
                        {
                            var keyInner = (i + 1) + "|" + (j + 1);
                            var to       = dict[keyInner];
                            gapi.AddEdge(from, to);
                        }
                    }
                }
            }

            CCForDFSHard cc = new CCForDFSHard(gapi);

            Array.Sort(cc.Id);

            return(cc.Id[cc.Id.Length - 1]);
        }
        static int minimumMoves(string[] grid, int startX, int startY, int goalX, int goalY)
        {
            int from = -1;
            int to   = -1;
            int n    = grid.Length;

            int[][] matrix  = new int[n][];
            int     tracker = 0;

            for (int i = 0; i < n; i++)
            {
                matrix[i] = new int[n];
                for (int j = 0; j < n; j++)
                {
                    if (grid[i][j] != 'X')
                    {
                        matrix[i][j] = tracker;
                    }
                    else
                    {
                        matrix[i][j] = -1;
                    }

                    tracker++;
                    if (startX == i && startY == j)
                    {
                        from = matrix[i][j];
                    }

                    if (goalX == i && goalY == j)
                    {
                        to = matrix[i][j];
                    }
                }
            }

            GraphAPI gapi = new GraphAPI(tracker);

            for (int i = 0; i < n; i++)
            {
                for (int j = 0; j < n; j++)
                {
                    if (i < n - 1 && matrix[i][j] != -1 && matrix[i + 1][j] != -1)
                    {
                        gapi.AddEdgeExt(matrix[i][j], matrix[i + 1][j], "V");
                    }

                    if (j < n - 1 && matrix[i][j] != -1 && matrix[i][j + 1] != -1)
                    {
                        gapi.AddEdgeExt(matrix[i][j], matrix[i][j + 1], "H");
                    }
                }
            }

            BFSForCastleGrid bfs = new BFSForCastleGrid(gapi, from);

            List <int> list           = bfs.PathTo(to).ToList();
            string     previousAllign = string.Empty;
            int        count          = 0;

            for (int i = 0; i < list.Count() - 1; i++)
            {
                string key  = list[i] < list[i + 1] ? list[i] + "|" + list[i + 1] : list[i + 1] + "|" + list[i];
                var    item = gapi.dict[key];

                if (previousAllign == string.Empty || previousAllign != item)
                {
                    count++;
                    previousAllign = item;
                }
            }

            return(count);
        }