public override Grafo getComplementar()
        {
            Grafo_Und          grafo;
            int                nVertices;
            List <ParOrdenado> pares = new List <ParOrdenado>();

            for (int i = 0; i < Vertices.Length; i++)
            {
                for (int j = 0; j < Vertices.Length; j++)
                {
                    if (i != j)
                    {
                        if (!isAdjacente(Vertices[i], Vertices[j]))
                        {
                            if (!VerificarParExistente(Vertices[i].ID, Vertices[j].ID, pares))
                            {
                                ParOrdenado par = new ParOrdenado(Vertices[i].ID, Vertices[j].ID);
                                pares.Add(par);
                            }
                        }
                    }
                }
            }

            nVertices = Vertices.Length;
            return(grafo = new Grafo_Und(nVertices, pares));
        }
        static void Main(string[] args)
        {
            /*
             * Grafo_Und grafoSemDirecao;
             *
             * //testes considerando um arquivo que dê um grafo com pelo menos 4 vertices
             * grafoSemDirecao = MontagemGrafoUnd("grafo.txt");
             * Vertice vertice1, vertice2, vertice3;
             * vertice1 = grafoSemDirecao.SelecionarVertice(0);
             * vertice2 = grafoSemDirecao.SelecionarVertice(1);
             * vertice3 = grafoSemDirecao.SelecionarVertice(2);
             * Console.WriteLine("TESTES EM GRAFOS NÃO DIRIGIDOS");
             * Console.WriteLine("V1 é adjacente a V3? {0}", grafoSemDirecao.isAdjacente(vertice1, vertice3));
             * Console.WriteLine("Qual o grau de V2?  {0}", grafoSemDirecao.getGrau(vertice2));
             * Console.WriteLine("O vertice V1 é isolado? {0}", grafoSemDirecao.isIsolado(vertice1));
             * Console.WriteLine("O vertice V2 é pendente? {0}", grafoSemDirecao.isPendente(vertice2));
             * Console.WriteLine("O grafo é regular? {0}", grafoSemDirecao.isRegular());
             * Console.WriteLine("O grafo é nulo? {0}", grafoSemDirecao.isNulo());
             * Console.WriteLine("O grafo é completo? {0}", grafoSemDirecao.isCompleto());
             * Console.WriteLine("O grafo é conexo? {0}", grafoSemDirecao.isConexo());
             */

            Grafo_Und grafoDirecionado = MontagemGrafoUnd("grafo.txt");
            Grafo_Und arvoreMinima     = grafoDirecionado.Kruskal();

            List <int> caminho = grafoDirecionado.Dijkstra(1, 4);

            foreach (int v in caminho)
            {
                Console.WriteLine(v + 1);
            }


            Console.ReadKey();
        }
        public Grafo_Und Kruskal()
        {
            //algoritmo só deve ser executado em grafos conexos
            if (!isConexo()) //se o grafo não é conexo, o algoritmo não será executado e retornará null
            {
                return(null);
            }

            //pré processamento dos dados
            List <Aresta>      listaArestas = new List <Aresta>();
            List <ParOrdenado> pares        = new List <ParOrdenado>();
            Grafo_Und          grafoAuxilir = new Grafo_Und(Vertices.Length, pares);

            for (int g = 0; g < Vertices.Length; g++)
            {
                for (int a = 0; a < Vertices[g].ListaDeAdjacencia.Count; a++)
                {
                    if (Vertices[g].ListaDeAdjacencia[a].Direcao == 1)
                    {
                        listaArestas.Add(Vertices[g].ListaDeAdjacencia[a]);
                    }
                }
            }

            Aresta[] arestasOrdenadas = insertionSort(listaArestas.ToArray());
            //dados processados e arestas já ordenadas

            //para cada aresta no vetor de aresta
            for (int v = 0; v < arestasOrdenadas.Length; v++)
            {
                //capturar origem e destino da aresta, ignorando a direção, pois é um grafo não dirigido
                int idOrigem  = arestasOrdenadas[v].verticeOrigem.ID;
                int idDestino = arestasOrdenadas[v].verticeDestino.ID;

                //if para ignorar os loops do grafo original
                if (idOrigem != idDestino)
                {
                    //fila auxiliar para executar a busca pelo ciclo
                    Queue <int> fila = new Queue <int>();

                    //verifica se a adição da nova aresta vai gerar um ciclo
                    if (!VerificarCiclo(fila, idOrigem, idDestino, idDestino, grafoAuxilir))
                    {
                        grafoAuxilir.FormarNovaAresta(idOrigem, idDestino, arestasOrdenadas[v].Peso); //não formando ciclo, nova aresta é criada
                    }
                }
            }

            return(grafoAuxilir);
        }
        static Grafo_Und MontagemGrafoUnd(string arqName)
        {
            Grafo_Und          grafo;
            StreamReader       reader    = new StreamReader(arqName);
            int                nVertices = int.Parse(reader.ReadLine());
            List <ParOrdenado> lista     = new List <ParOrdenado>();

            while (!reader.EndOfStream)
            {
                int      x, y, peso;
                string   linha    = reader.ReadLine();
                string[] vetSplit = linha.Split(';');
                x    = int.Parse(vetSplit[0]) - 1;
                y    = int.Parse(vetSplit[1]) - 1;
                peso = int.Parse(vetSplit[2]);
                ParOrdenado par = new ParOrdenado(x, y, peso);
                lista.Add(par);
            }

            reader.Close();

            return(grafo = new Grafo_Und(nVertices, lista));
        }
        private bool VerificarCiclo(Queue <int> fila, int idOrigem, int idDestino, int idAtual, Grafo_Und grafoAux)
        {
            //MÉTODO RECURSIVO BASEADO NA TRAVESSIA EM AMPLITUDE
            grafoAux.Vertices[idAtual].EstadoCor = 2;

            //para cada item da lista de adjacencia do vértice atual
            for (int w = 0; w < grafoAux.Vertices[idAtual].ListaDeAdjacencia.Count; w++)
            {
                //captura o indice do vertice destino
                int idLaco = grafoAux.Vertices[idAtual].ListaDeAdjacencia[w].verticeDestino.ID;

                //se o indice capturado for igual a origem, singnifica que esses componentes ja são conexos
                //a adição de uma nova aresta, formaria um ciclo, portanto, retorna verdadeiro
                if (idLaco == idOrigem)
                {
                    //reseta as cores do grafo auxiliar, para não atrapalhar as próximas execuções do algoritmo
                    grafoAux.ResetarCores();
                    return(true);
                }

                else
                {
                    //verifica se o vertice já não foi visitado anteriormente
                    if (grafoAux.Vertices[idLaco].EstadoCor == 1)
                    {
                        fila.Enqueue(idLaco);                    //enfileira o indice do vertice que está sendo visitado
                        grafoAux.Vertices[idLaco].EstadoCor = 2; //pinta o vertice de azul
                    }
                }
            }

            grafoAux.Vertices[idAtual].EstadoCor = 3; //pinta o vertice de vermelho

            //condição para chamada recursiva
            //se existem itens na fila, ainda há vertices para verificar a condição de ciclo
            if (fila.Count > 0)
            {
                //remove da fila, detectando o próximo vertice a ser verificado
                int prox = fila.Dequeue();

                //chamada recursiva com parametros atualizados
                return(VerificarCiclo(fila, idOrigem, idDestino, prox, grafoAux));
            }

            //else que será executado quando todos os vértices já tiverem sido visitados
            else
            {
                //reseta as cores do grafo auxiliar, para não atrapalhar as próximas execuções do algoritmo
                grafoAux.ResetarCores();
                return(false);
            }
        }