1 / 16

Pesquisa em profundidade

generalização da travessia em pré-ordem começando num vértice v, processa-se v e depois atravessa-se recursivamente todos os vértices adjacentes a v executada numa árvore — visita sistemática de todos os vértices, tempo O(|E|) executada num grafo arbitrário

gary
Télécharger la présentation

Pesquisa em profundidade

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. generalização da travessia em pré-ordem começando num vértice v, processa-se v e depois atravessa-se recursivamente todos os vértices adjacentes a v executada numa árvore — visita sistemática de todos os vértices, tempo O(|E|) executada num grafo arbitrário evitar os ciclos marcar os nós visitados para impedir a repetição grafo não dirigido/não conexo ou dirigido/não fortemente conexo: ficando vértices por visitar  percorrer lista de nós até ao seguinte não marcado Pesquisa em profundidade void dfs( Vertex v ) //Depth-first search { v.visited = true; for each w adjacent to v if( ! w.visited ) dfs( w ); } Esquema básico da pesquisa em profundidade

  2. um grafo não dirigido é conexo Û uma pesquisa em profundidade a começar em qualquer nó visita todos os nós começa-se por marcar A; 1º adjacente: B; recorre… - ao processar (v,w), se w não estiver marcado acrescenta-se a aresta na árvore - se já estiverem ambos marcados, acrescenta-se uma aresta de retorno (a ponteado) que não pertence à árvore (todas as arestas do grafo estão na árvore total) árvore simula a pesquisa; numeração em pré-ordem pelas arestas da árvore dá a ordem de marcação dos vértices 1 - Grafos não dirigidos A A B D B E C grafo árvore de expansão em profundidade C D E

  3. Aplicação - rede com tolerância a falhas Pontos de articulação - vértices que tornam o grafo desconexo (críticos) Algoritmo de detecção de pontos de articulação em tempo linear início num vértice qualquer pesquisa em profundidade, numerando os vértices ao visitá-los — Num(v), em pré-ordem para cada vértice na árvore de expansão calcular Low(v), o menor número de vértice que se atinge com zero ou mais arestas na árvore e possivelmente uma aresta de retorno (computável com travessia em pós-ordem) 2 - Biconectividade • Grafo conexo não dirigido é biconexo se • não existe nenhum vértice cuja remoção torne o resto do grafo desconexo

  4. Cálculo de Low(v) primeiro para os filhos e depois para o pai arestas (v,w) são da árvore se Num(v) < Num(w); de retorno no caso inverso basta percorrer a lista de adjacências; O( |E| + |V| ) Vértice v é ponto de articulação se tiver um filho w tal que Low(w)  Num(v) A raiz é ponto de articulação sse tiver mais que um filho na árvore Pontos de articulação • Low(v) é mínimo de • Num(v) • o menor Num(w) de todas as arestas (v,w) de retorno • o menor Low(w) de todas as arestas (v,w) da árvore

  5. Detecção de pontos de articulação grafo árvores de expansão em profundidade A B C,1/1 A,1/1 D C F D,2/1 G,7/7 B,2/1 E G C,3/1 F,4/2 E,3/2 A,5/1 B,6/1 D,4/1 G,7/7 v, Num(v)/Low(v) F,6/4 E,5/4 Pontos de articulação: C e D

  6. • Num(v) — pre-ordem • Low(v) — pos-ordem • pontos de articulação — pos-ordem Duas passagens? // Atribui numero e calcula pai // Contador global e inicializado a 1 void assignNum( Vertex v) { v.num = counter++; v.visited = true; for each w adjacent to v if( !w.visited ) { w.parent = v; assignNum(w); } } // Atribui Low // Testa Pontos de Articulação void assignLow( Vertex v) { v.low = v.num; //regra 1 for each w adjacent to v if(w.num > v.num) //ramo árvore { assignLow(w); if( w.low >= v.num ) System.out.println(v, “ Ponto de articulação”); v.low = min(v.low, w.low); //regra 3 } else if ( v.parent != w ) //retorno v.low = min(v.low, w.num); //regra 2 } combinados

  7. Uma só pesquisa em profundidade // Procura Pontos de Articulação // Contador global e inicializado a 1 void findArt( Vertex v) { v.visited = true; v.low = v.num = counter++; //regra 1 for each w adjacent to v if( !w.visited ) //ramo árvore { w.parent = v; findArt(w); if(w.low >= v.num ) System.out.println(v, “ Ponto de articulação”); v.low = min(v.low, w.low); //regra 3 } else if ( v.parent != w ) //retorno v.low = min(v.low, w.num); //regra 2 } Combina o pré-processamento e o pós-processamento numa única passagem

  8. Puzzle: desenhar as figuras abaixo sem levantar o lápis e sem repetir arestas; de preferência, terminando no mesmo vértice em que iniciar. 3 - Circuitos de Euler Reformulação do problema em Teoria de Grafos: pôr um vértice em cada intersecção Caminho de Euler: caminho que visita cada aresta exactamente uma vez problema resolvido por Euler em 1736 e que marca o início da Teoria dos Grafos

  9. método: pesquisa em profundidade O(|E| + |V| ) principal problema: fazer um curto-circuito e deixar arestas de fora correcção - procurar o primeiro vértice no caminho obtido que possua uma aresta não percorrida - lançar uma sub-pesquisa em profundidade - inserir o resultado no caminho principal (usar lista ligada) Ciclo Hamiltoniano: ciclo simples que visita todos os vértices? (vê-se depois) Solução • condição necessária • • circuito de Euler: número de arestas convergentes em cada vértice é par • - o ciclo entra tantas vezes em vértices quantas sai • • caminho de Euler: idem, excepto possivelmente em dois vértices • - o primeiro e o último; no caso de haver mais vértices com número ímpar de arestas é impossível • condição suficiente • • se se verificarem as condições acima, então existe circuito (caminho) de Euler

  10. Exemplo de um circuito 1 2 3 4 5 Grafo: existe caminho de Euler 7 6 8 9 10 11 12 1 2 3 4 5 Depois de fazer caminho 5, 4, 10, 5 7 6 8 9 10 11 12

  11. Exemplo de um circuito 1 2 3 4 5 Depois de fazer caminho 5, 4, 1,3,7,4,11,10,7,9,3,4,10, 5 7 6 8 9 10 11 12 1 2 3 4 5 Depois de fazer caminho 5, 4, 1, 3, 2, 8, 9, 6, 3, 7, 4, 11, 10, 7, 9, 3, 4, 10, 5 7 6 8 9 10 11 12

  12. (também) atravessáveis em tempo linear por pesquisa em profundidade (serve para detectar se grafo é acíclico) problema: se não for fortemente conexo, pesquisa em profundidade pode não visitar todos os nós Þ recomeçar a pesquisa num nó não visitado (nova raiz…) 4 - Grafos dirigidos A B G D C F H E J I

  13. pesquisa em profundidade induz uma árvore/floresta de expansão para além das arestas genuínas da árvore, há arestas para nós já marcados arestas de retorno para um antepassado — (A,B), (I,H) arestas de avanço para um descendente — (C,D), (C,E) arestas cruzadas para um nó não relacionado — (F,C), (G,F) • alguns algoritmos necessitam de distinguir estas categorias de arestas Árvore de expansão B H G C F A J D I E

  14. Método: pesquisa em profundidade no grafo G determina floresta de expansão, numerando vértices em pós-ordem inverter todas as arestas de G — Gr segunda pesquisa em profundidade, em Gr, começando sempre pelo vértice de numeração mais alta ainda não visitado cada árvore obtida é um componente fortemente conexo, i.e., a partir de um qualquer dos nós pode chegar-se a todos os outros Prova mesmo componente Þ mesma árvore de expansão se dois vértices v e w estão no mesmo componente, há caminhos de v para w e de w para v em G e em Gr; se v e w não pertencerem à mesma árvore de expansão, também não estão no mesmo componente mesma árvore de expansão Þ mesmo componente i.e., há caminhos de v para w e de w para v ou, equivalentemente, se x for a raiz de uma árvore de expansão em profundidade, há caminhos de x para v e de v para x, de x para w e de w para x e portanto entre v e w como v é descendente de x na árvore de Gr, há um caminho de x para v em Gr, logo de v para x em G; como x é a raiz tem o maior número de pós-ordem na primeira pesquisa; portanto, na primeira pesquisa, todo o processamento de v se completou antes de o trabalho em x ter terminado; como há um caminho de v para x, segue-se que v tem que ser um descendente de x na árvore de expansão — caso contrário v terminaria depois de x; isto implica um caminho de x para v em G. Componentes fortemente conexos

  15. Componentes fortemente conexos A,3 B,6 G,10 D,2 C,4 F,5 H,9 E,1 J,8 I,7 Gr: obtido de G por inversão de todas as arestas Numeração: da travessia de G em pós-ordem

  16. Componentes fortemente conexos G H B D E A I C J F Travessia em pós-ordem de Gr Componentes fortemente conexos: {G}, {H, I, J}, {B, A, C, F}, {D}, {E}

More Related