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); } }