static Grafo_Dir MontagemGrafoDir(string arqName) { Grafo_Dir 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, direcao; 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]); direcao = int.Parse(vetSplit[3]); if (direcao == -1) { int aux = x; x = y; y = aux; } ParOrdenado par = new ParOrdenado(x, y, peso); lista.Add(par); } reader.Close(); return(grafo = new Grafo_Dir(nVertices, lista)); }
public Grafo_Dir 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_Dir grafoAuxilir = new Grafo_Dir(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); }
private bool VerificarCiclo(Queue <int> fila, int idOrigem, int idDestino, int idAtual, Grafo_Dir 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++) { //se a direção é origem -> destino if (grafoAux.Vertices[idAtual].ListaDeAdjacencia[w].Direcao == 1) { //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); } }