Вы находитесь на странице: 1из 31

1

Conceitos de Grafos

1 Introduo Muitas aplicaes em computao necessitam considerar conjunto de conexes entre pares de objetos: Existe um caminho para ir de um objeto a outro seguindo as conexes? Qual a menor distncia entre um objeto e outro objeto? Quantos outros objetos podem ser alcanados a partir de um determinado objeto? Existe um tipo abstrato chamado grafo que usado para modelar tais situaes.

2 Aplicaes Alguns exemplos de problemas prticos que podem ser resolvidos atravs de uma modelagem em grafos: Ajudar mquinas de busca a localizar informao relevante na Web. Descobrir os melhores casamentos entre posies disponveis em empresas e pessoas que aplicaram para as posies de interesse. Descobrir qual o roteiro mais curto para visitar as principais cidades de uma regio turstica ou uma boa rota para ir a um restaurante.

3 Breve Histrico Marco Inicial A teoria dos grafos surgiu de um problema algortimico: o problema da ponte de Knigsberg, resolvido por Euler em 1736. Na cidade de Knigsberg na Rssia existem duas ilhas sobre o rio Pregel com um total de 7 pontes interligando as regies. O problema consiste em partindo de uma dessas regies, determinar um trajeto pelas pontes segundo o qual se possa retornar regio de partida, aps atravessar cada ponte somente uma vez.

Euler mostrou que no existe tal trajeto utilizando um modelo em grafos para uma generalizao deste problema.

Atravs desse modelo, Euler provou que existe o desejado trajeto quando e somente quando em cada regio concorrer um nmero par de pontes. Esta soluo considerada o primeiro teorema em teoria dos grafos.

4 Conceitos Bsicos

Definio de grafos - Abstrao matemtica que representa situaes reais atravs de um diagrama.

Diagrama - Corresponde a soma de pontos e linhas, onde os pontos apresentam alguma informao e as linhas indicam o relacionamento entre dois pontos quaisquer.

Aplicaes - Gentica, Qumica, Pesquisa operacional, Telecomunicaes, Computao, Engenharia Eltrica, dentre outros.

Estudar grafos em Computao significa aprender mais uma forma de solucionar problemas computveis.

Grafo: conjunto de vrtices e arestas. Vrtice: objeto simples que pode ter nome e outros atributos. Aresta: conexo entre dois vrtices.

Notao: G = (V,A) G: grafo V: conjunto de vrtices A: conjunto de ar estas

Grafos Direcionados ou Dgrafos Um grafo direcionado G um par (V,A), onde V um conjunto finito de vrtices e A uma relao binria em V ({0,1},{0,3},{1,2},{1,3},{2,2},{2,3},{3,0},{5,4}) Uma aresta (u, v) sai do vrtice u e entra no vrtice v. O vrtice v adjacente ao vrtice u. Podem existir arestas de um vrtice para ele mesmo, chamadas de self-loops.

Grafos No Direcionados Um grafo no direcionado G um par (V,A), onde o conjunto de arestas A constitudo de pares de vrtices no ordenados. As arestas (u, v) e (v, u) so consideradas como uma nica aresta. A relao de adjacncia simtrica. Self-loops no so permitidos.

Grau de um Vrtice Em grafos no direcionados: O grau de um vrtice o nmero de arestas que incidem nele. Um vrtice de grau zero dito isolado ou no conectado. Ex.: O vrtice 1 tem grau 2 e o vrtice 3 isolado.

Em grafos direcionados O grau de um vrtice o nmero de arestas que saem dele (out-degree) mais o nmero de arestas que chegam nele (in-degree). Ex.: O vrtice 2 tem in-degree 2, out-degree 2 e grau 4.

Caminho entre Vrtices Um caminho de comprimento k de um vrtice x a um vrtice y em um grafo G = (V;A) uma seqncia de vrtices (v0, v1, v2, ... ,vk) tal que x = v0 e y = vk, e vi 1, vi) pertence a A para i = 1, 2, ... ,k. O comprimento de um caminho o nmero de arestas nele, isto , o caminho contm os vrtices v0, v1, v2, ..., vk e as arestas (v0, v1), (v1, v2),..., (vk-1, vk). Se existir um caminho c de x a y ento y alcanvel a partir de x via c.

Um caminho simples se todos os vrtices do caminho so distintos. Ex.: O caminho (0, 1, 2, 3) simples e tem comprimento 3. O caminho (1, 3, 0, simples. 3) no

Ciclos Em um grafo direcionado: Um caminho (v0, v1, ... , vk) forma um ciclo se v0 = vk e o caminho contm pelo menos uma aresta. O ciclo simples se os vrtices v1, v2, ..., vk so distintos. O self-loop um ciclo de tamanho 1. Dois caminhos (v0, v1, ..., vk) e (v0, v1, ..., vk) formam o mesmo ciclo se existir um inteiro j tal que vi = v(i+j) mod k para i = 0, 1,..., k-1. Ex.: O caminho (0, 1, 2, 3, 0) forma um ciclo. O caminho (0, 1, 3, 0) forma o mesmo ciclo que os caminhos (1, 3, 0, 1) e (3, 0, 1, 3).

Em um grafo no direcionado: Um caminho (v0, v1, ...,vk) forma um ciclo se v0 = vk e o caminho contm pelo menos trs arestas. O ciclo simples se os vrtices v1, v2, ... , vk so distintos. Ex.: O caminho (0, 1, 2, 0) um ciclo.

Componentes Conectados Um grafo no direcionado conectado se cada par de vrtices est conectado por um caminho. Os componentes conectados so as pores conectadas de um grafo. Um grafo no direcionado conectado se ele tem exatamente um componente conectado. Ex.: Os componentes so: {0,1,2}, {4,5} e {3}.

Componentes Fortemente Conectados Um grafo direcionado G = (V,A) fortemente conectado se cada dois vrtices quaisquer so alcanveis a partir um do outro. Os componentes fortemente conectados de um grafo direcionado so conjuntos de vrtices sob a relao so mutuamente alcanveis. Um grafo direcionado fortemente conectado tem apenas um componente fortemente conectado.

Ex. {0,1,2,3}, {4} e {5} so os componentes fortemente conectado, {4,5} no o pois o vrtice 5 no alcanvel a partir do vrtice 4.

Outros tipos de grafos Grafo ponderado: possui pesos associados s arestas. Hipergrafo: grafo no direcionado em que cada aresta conecta um nmero arbitrrio de vrtices. Grafos valorados (Redes): Uma Rede um grafo no-direcionado (ou um digrafo) no qual um nmero real associado aos vrtices e/ou ligaes. Este nmero freqentemente referido como o peso da ligao. Essa classificao dada de acordo com a necessidade, ou no, da indicao do fluxo entre os vrtices. Na prtica este nmero pode representar: - custos, distncias, capacidades, e/ou suprimentos e demandas; - tempo (trnsito, permanncia, etc); - confiabilidade de transmisso; - probabilidade de ocorrer falhas; - capacidade de carga.

Exemplos: Redes ferrovirias Redes de telecomunicaes Redes de estradas Redes Eltricas Redes de esgotos Redes de transportes Redes de atividades: scheduling de atividades em grandes projetos

Ns, vrtices ->atividades Arcos . restries de precedncia

5 O Tipo Abstratos de Dados Grafo Importante considerar os algoritmos em grafos como tipos abstratos de dados. Conjunto de operaes associado a uma estrutura de dados. Independncia de implementao para as operaes.

Operadores do TAD Grafo 1. FGVazio(Grafo): Cria um grafo vazio. 2. InsereAresta(V1,V2,Peso, Grafo): Insere uma aresta no grafo. 3. ExisteAresta(V1,V2,Grafo): Verifica se existe uma determinada aresta. 4. Obtem a lista de vrtices adjacentes a um determinado vrtice. 5. RetiraAresta(V1,V2,Peso, Grafo): Retira uma aresta do grafo. 6. LiberaGrafo(Grafo): Liberar o espao ocupado por um grafo. 7. ImprimeGrafo(Grafo): Imprime um grafo. 8. GrafoTransposto(Grafo,GrafoT): Obtm o transposto de um grafo direcionado. 9. RetiraMin(A): Obtm a aresta de menor peso de um grafo com peso nas arestas.

6 Formas de Representao Estrutura de Dados

6.1 Matriz de Adjacncia A matriz de adjacncia de um grafo G = (V,A) contendo n vrtices uma matriz n x n de bits, onde A[i, j] 1 (ou verdadeiro) se e somente se existe um arco do vrtice i para o vrtice j. Para grafos ponderados A[i, j] contm o rtulo ou peso associado com a aresta e, neste caso, a matriz no de bits. Se no existir uma aresta de i para j ento necessrio utilizar um valor que no possa ser usado como rtulo ou peso.

10

Matriz de Adjacncia - Anlise Deve ser utilizada para grafos densos, onde |Aj| prximo de |V |2. O tempo necessrio para acessar um elemento independente de |V| ou |A|. muito til para algoritmos em que necessitamos saber com rapidez se existe uma aresta ligando dois vrtices. A maior desvantagem que a matriz necessita de espao de armazenamento. Ler ou examinar a matriz tem complexidade de tempo O(|V|2). A insero de um novo vrtice ou retirada de um vrtice j existente pode ser realizada com custo constante.

Implementao de operaes (www.dcc.ufmg.br/algoritmos)


#include<stdlib.h> #include<stdio.h> #define MaxNumVertices 100

11

#define MaxNumArestas #define TRUE 1 #define FALSE 0

4500

typedef int TipoValorVertice; typedef int TipoPeso;

typedef struct TipoGrafo { TipoPeso Mat[MaxNumVertices + 1][MaxNumVertices + 1]; int NumVertices; int NumArestas; } TipoGrafo; typedef int Apontador;

Apontador Aux; int i; TipoValorVertice V1, V2, Adj; TipoPeso Peso; TipoGrafo Grafo, Grafot; TipoValorVertice NVertices; short NArestas; short FimListaAdj;

void FGVazio(TipoGrafo *Grafo) { short i, j; for (i = 0; i <= Grafo->NumVertices; i++) { for (j = 0; j <=Grafo->NumVertices; j++) Grafo->Mat[i][j] = 0; } }

void InsereAresta(TipoValorVertice *V1, TipoValorVertice *V2, TipoPeso *Peso, TipoGrafo *Grafo) { Grafo->Mat[*V1][*V2] = *Peso; }

12

short ExisteAresta(TipoValorVertice Vertice1, TipoValorVertice Vertice2, TipoGrafo *Grafo) { return (Grafo->Mat[Vertice1][Vertice2] > 0); } /* ExisteAresta */

/*-- Operadores para obter a lista de adjacentes --*/ short ListaAdjVazia(TipoValorVertice *Vertice, TipoGrafo *Grafo) { Apontador Aux = 0; short ListaVazia = TRUE; while (Aux < Grafo->NumVertices && ListaVazia) { if (Grafo->Mat[*Vertice][Aux] > 0) ListaVazia = FALSE; else Aux++; } return (ListaVazia == TRUE); } /* ListaAdjVazia */

Apontador PrimeiroListaAdj(TipoValorVertice *Vertice, TipoGrafo *Grafo) { TipoValorVertice Result; Apontador Aux = 0; short ListaVazia = TRUE; while (Aux < Grafo->NumVertices && ListaVazia) { if (Grafo->Mat[*Vertice][Aux] > 0) { Result = Aux; ListaVazia = FALSE; } else Aux++; } if (Aux == Grafo->NumVertices) printf("Erro: Lista adjacencia vazia (PrimeiroListaAdj)\n"); return Result; } /* PrimeiroListaAdj */

13

void ProxAdj(TipoValorVertice *Vertice, TipoGrafo *Grafo, TipoValorVertice *Adj, TipoPeso *Peso, Apontador *Prox, short *FimListaAdj) { /* --Retorna Adj apontado por Prox--*/ *Adj = *Prox; *Peso = Grafo->Mat[*Vertice][*Prox]; (*Prox)++; while (*Prox < Grafo->NumVertices && Grafo->Mat[*Vertice][*Prox] == 0) (*Prox)++; if (*Prox == Grafo->NumVertices) *FimListaAdj = TRUE; } /* ProxAdj- */

void RetiraAresta(TipoValorVertice *V1, TipoValorVertice *V2, TipoPeso *Peso, TipoGrafo *Grafo) { if (Grafo->Mat[*V1][*V2] == 0) printf("Aresta nao existe\n"); else { *Peso = Grafo->Mat[*V1][*V2]; Grafo->Mat[*V1][*V2] = 0; } } /* RetiraAresta */

void LiberaGrafo(TipoGrafo *Grafo) { /* Nao faz nada no caso de matrizes de adjacencia */ } /* LiberaGrafo */

void ImprimeGrafo(TipoGrafo *Grafo) { short i, j; printf(" "); for (i = 0; i <= Grafo->NumVertices - 1; i++) printf("%3d", i); printf("\n"); for (i = 0; i <= Grafo->NumVertices - 1; i++) { printf("%3d", i); for (j = 0; j <=Grafo->NumVertices - 1; j++)

14

printf("%3d", Grafo->Mat[i][j]); printf("\n"); } } /* ImprimeGrafo */

void GrafoTransposto(TipoGrafo *Grafo, TipoGrafo *GrafoT) { TipoValorVertice v, Adj; TipoPeso Peso; Apontador Aux; FGVazio(GrafoT); GrafoT->NumVertices = Grafo->NumVertices; GrafoT->NumArestas = Grafo->NumArestas; for (v = 0; v <= Grafo->NumVertices - 1; v++) { if (!ListaAdjVazia(&v, Grafo)) { Aux = PrimeiroListaAdj(&v, Grafo); FimListaAdj = FALSE; while (!FimListaAdj) { ProxAdj(&v, Grafo, &Adj, &Peso, &Aux, &FimListaAdj); InsereAresta(&Adj, &v, &Peso, GrafoT); } } } } /* GrafoTransposto */

/* ============================================================= */ int main() { /*-- Programa principal --*/ /* -- NumVertices: definido antes da leitura das arestas --*/ /* -- NumArestas: inicializado com zero e incrementado a --*/ /* -- cada chamada de InsereAresta --*/ printf("Leitura do grafo\n"); printf("No. vertices:"); scanf("%d%*[^\n]", &NVertices); getchar(); printf("No. arestas:"); scanf("%hd%*[^\n]", &NArestas); getchar(); Grafo.NumVertices = NVertices; Grafo.NumArestas = 0;

15

FGVazio(&Grafo); for (i = 0; i <= NArestas - 1; i++) { printf("Insere V1 -- V2 -- Peso:"); scanf("%d%d%d%*[^\n]", &V1, &V2, &Peso); getchar(); Grafo.NumArestas++; InsereAresta(&V1, &V2, &Peso, &Grafo); /* 1 chamada g-direcionado */ /*InsereAresta(V2, V1, Peso, Grafo);*/ /* 2 chamadas g-naodirecionado*/ } printf ("Imprimindo o grafo\n"); ImprimeGrafo(&Grafo); scanf("%*[^\n]"); getchar(); GrafoTransposto(&Grafo, &Grafot); printf("Imprimindo o grafo transposto\n"); ImprimeGrafo(&Grafot); scanf("%*[^\n]"); getchar(); printf("Incluindo uma nova aresta no grafo\n"); printf("Insere V1 -- V2 -- Peso:"); scanf("%d%d%d%*[^\n]", &V1, &V2, &Peso); getchar(); if (ExisteAresta(V1, V2, &Grafo)) printf("Aresta ja existe\n"); else { Grafo.NumArestas++; InsereAresta(&V1, &V2, &Peso, &Grafo); /*InsereAresta(V2, V1, Peso, Grafo);*/ /* grafo nao direcionado */ } printf("Imprimindoo grafo novamente\n"); ImprimeGrafo(&Grafo); scanf("%*[^\n]"); getchar(); printf("Lista adjacentes de: "); scanf("%d", &V1); if (!ListaAdjVazia(&V1, &Grafo)) { Aux = PrimeiroListaAdj(&V1, &Grafo); FimListaAdj = FALSE; while (!FimListaAdj) { ProxAdj(&V1, &Grafo, &Adj, &Peso, &Aux, &FimListaAdj); printf("%2d (%d)", Adj, Peso); } putchar('\n'); scanf("%*[^\n]");

16

getchar(); } printf("Retira aresta V1 -- V2:"); scanf("%d%d%*[^\n]", &V1, &V2); getchar(); if (ExisteAresta(V1, V2, &Grafo)) { Grafo.NumArestas--; RetiraAresta(&V1, &V2, &Peso, &Grafo); /*RetiraAresta(V2, V1, Peso, Grafo);*/ } else printf("Aresta nao existe\n"); ImprimeGrafo(&Grafo); scanf("%*[^\n]"); getchar(); printf("Existe aresta V1 -- V2:"); scanf("%d%d%*[^\n]", &V1, &V2); getchar(); if (ExisteAresta(V1, V2, &Grafo)) printf(" Sim\n"); else printf(" Nao\n"); LiberaGrafo(&Grafo); ImprimeGrafo(&Grafo); return 0; } /* End. */

17

6.2 Listas de Adjacncia usando Apontadores

Listas de adjacncia - Anlise Os vrtices de uma lista de adjacncia so em geral armazenados em uma ordem arbitrria. Indicada para grafos esparsos. compacta e usualmente utilizada na maioria das aplicaes. A principal desvantagem determinar se existe uma aresta entre o vrtice i e o vrtice j.

Listas de Adjacncia usando Apontadores - Implementao No uso de apontadores a lista constituda de clulas, onde cada clula contm um item da lista e um apontador para a clula seguinte.
#include <stdio.h> #include <stdlib.h> #define MaxNumVertices 100 #define MaxNumArestas 4500 #define FALSE 0 #define TRUE 1 typedef int TipoValorVertice;

18

typedef int TipoPeso; typedef struct TipoItem { TipoValorVertice Vertice; TipoPeso Peso; } TipoItem; typedef struct Struct_Celula *Apontador; struct Struct_Celula { TipoItem Item; Apontador Prox; }; typedef struct Struct_Celula Celula; typedef struct TipoLista { Apontador Primeiro, Ultimo; } TipoLista; typedef struct TipoGrafo { TipoLista Adj[MaxNumVertices + 1]; TipoValorVertice NumVertices; short NumArestas; } TipoGrafo; Apontador Aux; long i; TipoValorVertice V1, V2, Adj; TipoPeso Peso; TipoGrafo Grafo, GrafoT; TipoValorVertice NVertices; int NArestas; short FimListaAdj; /*--Entram aqui os operadores do Programa 2.4--*/ void FLVazia(TipoLista *Lista) { Lista->Primeiro = (Apontador)malloc(sizeof(Celula)); Lista->Ultimo = Lista->Primeiro; Lista->Primeiro->Prox = NULL; } short Vazia(TipoLista Lista) { return (Lista.Primeiro == Lista.Ultimo); } void Insere(TipoItem *x, TipoLista *Lista) { /*-- Insere depois do ultimo item da lista --*/ Lista->Ultimo->Prox = (Apontador)malloc(sizeof(Celula)); Lista->Ultimo = Lista->Ultimo->Prox; Lista->Ultimo->Item = *x; Lista->Ultimo->Prox = NULL; } /*-- Fim operadores do Programa 2.4 --*/

19

void FGVazio(TipoGrafo *Grafo) { long i; for (i = 0; i < Grafo->NumVertices; i++) FLVazia(&Grafo->Adj[i]); } void InsereAresta(TipoValorVertice *V1, TipoValorVertice *V2, TipoPeso *Peso, TipoGrafo *Grafo) { TipoItem x; x.Vertice = *V2; x.Peso = *Peso; Insere(&x, &Grafo->Adj[*V1]); } short ExisteAresta(TipoValorVertice Vertice1, TipoValorVertice Vertice2, TipoGrafo *Grafo) { Apontador Aux; short EncontrouAresta = FALSE; Aux = Grafo->Adj[Vertice1].Primeiro->Prox; while (Aux != NULL && EncontrouAresta == FALSE) { if (Vertice2 == Aux->Item.Vertice) EncontrouAresta = TRUE; Aux = Aux->Prox; } return EncontrouAresta; } /*-- Operadores para obter a lista de adjacentes --*/ short ListaAdjVazia(TipoValorVertice *Vertice, TipoGrafo *Grafo) { return (Grafo->Adj[*Vertice].Primeiro == Grafo->Adj[*Vertice].Ultimo); } Apontador PrimeiroListaAdj(TipoValorVertice *Vertice, TipoGrafo *Grafo) { return (Grafo->Adj[*Vertice].Primeiro->Prox); } void ProxAdj(TipoValorVertice *Vertice, TipoGrafo *Grafo, TipoValorVertice *Adj, TipoPeso *Peso, Apontador *Prox, short *FimListaAdj) { /* --Retorna Adj e Peso do Item apontado por Prox--*/ *Adj = (*Prox)->Item.Vertice; *Peso = (*Prox)->Item.Peso; *Prox = (*Prox)->Prox; if (*Prox == NULL) *FimListaAdj = TRUE; } void Retira(Apontador p, TipoLista *Lista, TipoItem *Item) { /*--Obs.: item a ser retirado e o seguinte ao apontado por p--*/ Apontador q; if (Vazia(*Lista) || p == NULL || p->Prox == NULL) { printf("Erro: Lista vazia ou posicao nao existe\n");

20

return; } q = p->Prox; *Item = q->Item; p->Prox = q->Prox; if (p->Prox == NULL) Lista->Ultimo = p; free(q); } void RetiraAresta(TipoValorVertice *V1, TipoValorVertice *V2, TipoPeso *Peso, TipoGrafo *Grafo) { Apontador AuxAnterior, Aux; short EncontrouAresta = FALSE; TipoItem x; AuxAnterior = Grafo->Adj[*V1].Primeiro; Aux = Grafo->Adj[*V1].Primeiro->Prox; while (Aux != NULL && EncontrouAresta == FALSE) { if (*V2 == Aux->Item.Vertice) { Retira(AuxAnterior, &Grafo->Adj[*V1], &x); Grafo->NumArestas--; EncontrouAresta = TRUE; } AuxAnterior = Aux; Aux = Aux->Prox; } } void LiberaGrafo(TipoGrafo *Grafo) { Apontador AuxAnterior, Aux; for (i = 0; i < Grafo->NumVertices; i++) { Aux = Grafo->Adj[i].Primeiro->Prox; free(Grafo->Adj[i].Primeiro); /*Libera celula cabeca*/ Grafo->Adj[i].Primeiro=NULL; while (Aux != NULL) {AuxAnterior = Aux; Aux = Aux->Prox; free(AuxAnterior); } } Grafo->NumVertices = 0; } void ImprimeGrafo(TipoGrafo *Grafo) { int i; Apontador Aux; for (i = 0; i < Grafo->NumVertices; i++) { printf("Vertice%2d:", i); if (!Vazia(Grafo->Adj[i])) { Aux = Grafo->Adj[i].Primeiro->Prox; while (Aux != NULL) { printf("%3d (%d)", Aux->Item.Vertice, Aux->Item.Peso); Aux = Aux->Prox; } }

21

putchar('\n'); } } void ImprimeLista(TipoLista Lista) { Apontador Aux; Aux = Lista.Primeiro->Prox; while (Aux != NULL) { printf("%3d (%12d)", Aux->Item.Vertice, Aux->Item.Peso); Aux = Aux->Prox; } } void GrafoTransposto(TipoGrafo *Grafo, TipoGrafo *GrafoT) { TipoValorVertice v, Adj; TipoPeso Peso; Apontador Aux; GrafoT->NumVertices = Grafo->NumVertices; GrafoT->NumArestas = Grafo->NumArestas; FGVazio(GrafoT); for (v = 0; v <= Grafo->NumVertices - 1; v++) { if (!ListaAdjVazia(&v, Grafo)) { Aux = PrimeiroListaAdj(&v, Grafo); FimListaAdj = FALSE; while (!FimListaAdj) { ProxAdj(&v, Grafo, &Adj, &Peso, &Aux, &FimListaAdj); InsereAresta(&Adj, &v, &Peso, GrafoT); } } } } /* ============================================================= */ int main(int argc, char *argv[]) { /*-- Programa principal --*/ int TEMP; int TEMP1; /* -- NumVertices: definido antes da leitura das arestas --*/ /* -- NumArestas: inicializado com zero e incrementado a --*/ /* -- cada chamada de InsereAresta --*/ printf("No. vertices:"); scanf("%d%*[^\n]", &TEMP); getchar(); NVertices = TEMP; printf("No. arestas:"); scanf("%d%*[^\n]", &NArestas); getchar(); Grafo.NumVertices = NVertices; Grafo.NumArestas = 0; FGVazio(&Grafo);

22

for (i = 0; i < NArestas; i++) { printf("Insere V1 -- V2 -- Peso:"); scanf("%d%d%d%*[^\n]", &TEMP, &TEMP1, &Peso); getchar(); V1 = TEMP; V2 = TEMP1; Grafo.NumArestas++; InsereAresta(&V1, &V2, &Peso, &Grafo); */ /*InsereAresta(V2, V1, Peso, Grafo);*/ /* 2 chamadas g-naodirecionado*/ } ImprimeGrafo(&Grafo); scanf("%*[^\n]"); getchar(); printf("Grafo transposto:\n"); GrafoTransposto(&Grafo, &GrafoT); ImprimeGrafo(&GrafoT); scanf("%*[^\n]"); getchar(); printf("Insere V1 -- V2 -- Peso:"); scanf("%d%d%d%*[^\n]", &V1, &V2, &Peso); if (ExisteAresta(V1, V2, &Grafo)) printf("Aresta ja existe\n"); else { Grafo.NumArestas++; InsereAresta(&V1, &V2, &Peso, &Grafo); /*InsereAresta(V2, V1, Peso, Grafo);*/ } ImprimeGrafo(&Grafo); scanf("%*[^\n]"); getchar(); printf("Lista adjacentes de: "); scanf("%d*[^\n]", &TEMP); V1 = TEMP; if (!ListaAdjVazia(&V1, &Grafo)) { Aux = PrimeiroListaAdj(&V1, &Grafo); FimListaAdj = FALSE; while (!FimListaAdj) { ProxAdj(&V1, &Grafo, &Adj, &Peso, &Aux, &FimListaAdj); printf("%2d (%d)", Adj, Peso); } putchar('\n'); scanf("%*[^\n]"); getchar(); } printf("Retira aresta V1 -- V2:"); scanf ("%d %d", &V1, &V2); if (ExisteAresta(V1, V2, &Grafo)) { Grafo.NumArestas--; RetiraAresta(&V1, &V2, &Peso, &Grafo); /*RetiraAresta(V2, V1, Peso, Grafo);*/ } else printf("Aresta nao existe\n"); ImprimeGrafo(&Grafo);

/* 1 chamada g-direcionado

23

scanf("%*[^\n]"); getchar(); printf("Existe aresta V1 -- V2:"); /* scanf("%d%d%*[^\n]", &TEMP, &TEMP1); */ scanf("%d*[^\n]", &TEMP); scanf("%d*[^\n]", &TEMP1);

getchar(); V1 = TEMP; V2 = TEMP1; if (ExisteAresta(V1, V2, &Grafo)) printf(" Sim\n"); else printf(" Nao\n"); LiberaGrafo(&Grafo); /* Imprime sujeira normalmente */ ImprimeGrafo(&Grafo); return 0; }

24

Operaes em grafos

Busca em Profundidade _ A busca em profundidade, do ingls depth-first search), um algoritmo para caminhar no grafo. _ A estratgia buscar o mais profundo no grafo sempre que possvel. _ As arestas so exploradas a partir do vrtice v mais recentemente descoberto que ainda possui arestas no exploradas saindo dele. _ Quando todas as arestas adjacentes a v tiverem sido exploradas a busca anda para trs para explorar vrtices que saem do vrtice do qual v foi descoberto. _ O algoritmo a base para muitos outros algoritmos importantes, tais como verificao de grafos acclicos, ordenao topolgica e componentes fortemente conectados.

Para acompanhar o progresso do algoritmo cada vrtice colorido de branco, cinza ou preto. _ Todos os vrtices so inicializados branco. _ Quando um vrtice descoberto pela primeira vez ele torna-se cinza, e tornado preto quando sua lista de adjacentes tenha sido completamente examinada. _ d[v]: tempo de descoberta _ t[v]: tempo de trmino do exame da lista de adjacentes de v. _ Estes registros so inteiros entre 1 e 2[V] pois existe um evento de descoberta e um evento de trmino para cada um dos [V] vrtices.

25

Busca em Largura Expande a fronteira entre vrtices descobertos e no descobertos uniformemente atravs da largura da fronteira. algoritmo descobre todos os vrtices a uma distncia k do vrtice origem antes de descobrir qualquer vrtice a uma distncia k + 1. O grafo G(V;A) pode ser direcionado ou no direcionado. Cada vrtice colorido de branco, cinza ou preto. Todos os vrtices so inicializados branco. Quando um vrtice descoberto pela primeira vez ele torna-se cinza. Vrtices cinza e preto j foram descobertos, mas so distinguidos para assegurar que a busca ocorra em largura.

Se (u; v) pertence a A e o vrtice u preto, ento o vrtice v tem que ser cinza ou preto. Vrtices cinza podem ter alguns vrtices adjacentes brancos, e eles representam a fronteira entre vrtices descobertos e no descobertos.

26

Problema das Praias

Florianpolis uma cidade que possui 42 praias. Para garantir a segurana dos veranistas o Corpo de Bombeiros sugeriu ao Governo do Estado o estabelecimento de bases de operao de busca, salvamento e atendimentos emergenciais. Contudo, dada a escassez de recursos, o Governo do Estado no julga vivel implementar estas bases em todas as praias. Desta forma, ele solicitou um estudo ao Corpo de Bombeiros visando definir um conjunto de praias candidatas, considerando que uma vez implantada uma base numa das praias esta base pode atender a todas as praias vizinhas que estejam a menos de 5 km dela via estrada. Como se poderia identificar este conjunto de praias candidatas.

27

Problema das 3 casas

Suponha que tenhamos trs casas e trs servios, a exemplo de:

possvel conectar cada servio a cada uma das trs casas sem que haja cruzamento de tubulaes?

Problema das Pontes de Knigsberg

No sculo 18 havia na cidade de Knigsberg um conjunto de sete pontes (identificadas pelas letras de a at f na figura abaixo) que cruzavam o rio Pregel . Elas conectavam duas ilhas entre si e as ilhas com as margens.

Por muito tempo os habitantes daquela cidade perguntavam-se se era possvel cruzar as sete pontes numa caminhada contnua sem passar duas vezes por qualquer uma delas.

28

Problema do metr

Considere a rede de metr de uma cidade como Barcelona, na Espanha. Esta rede cobre boa parte da cidade, sendo composta por vrias linhas que se cruzam em estaes especficas. Nestes pontos de cruzamento um usurio pode livremente sair de uma composio e passar para uma composio de outra linha. Sendo assim, em geral o usurio tem mais de uma opo de rota quando deseja deslocar-se de uma parte a outra da cidade. Escolher a melhor rota passa, ento, a ser fundamental para que o deslocamento seja o mais rpido possvel. As distncias entre estaes vizinhas do metr no so iguais e, consequentemente, o tempo de deslocamento entre estaes vizinhas no constante. Estas diferenas de tempo no so, contudo, significativas quando comparadas com os tempos de parada das composies nas estaes e de troca de composio (de linha). Em redes de metr de vrias cidades do mundo h sistemas computacionais que auxiliam os usurios a escolher a melhor rota para um deslocamento particular. Mais do que simplesmente indicar uma rota possvel, estes sistemas procuram identificar aquela rota que conduz o usurio o mais rapidamente ao seu destino. Dois critrios bsicos para esta escolha so (em ordem de importncia): procurar minimizar o nmero de trocas de composio (de linhas); procurar minimizar o nmero de paradas em estaes.

29

Mapa do Metr da cidade de Barcelona (Espanha)

30

Problema do caminho de custo mnimo

De forma a reduzir seus custos operacionais, uma empresa de transporte de cargas deseja oferecer aos motoristas de sua frota um mecanismo que os auxilie a selecionar o caminho de menor custo entre quaisquer duas cidades por ela servidas. Como realizar esta tarefa?

31

Problema da Carga Pesada

Um dos maiores problemas no transporte de cargas pesadas por rodovias a altura dos viadutos, pois muitas vezes a carga mais alta do que o vo do viaduto sob o qual o caminho deve passar. Considere o mapa abaixo. possvel transportar uma turbina de hidroeltrica, que em cima do caminho mede 7 metros de altura, da cidade Xis da Serra para a cidade Ypsilon Bonito?

Neste caso fcil perceber que a resposta sim, pois o menor vo encontrado no caminho, se utilizarmos as estradas BR-1001 e BR-1024, de 9 metros. No caso geral, com dezenas de cidades e estradas, a resposta pode no ser to evidente. Conhecendo todas as estradas da regio e a altura de todos os tneis e viadutos dessas estradas, e dado que temos uma carga de uma determinada altura, como se poderia determinar qual o melhor trajeto para levar a carga de um lugar para outro qualquer desta regio?

Вам также может понравиться