Análise e Síntese de Algoritmos Algoritmos em Grafos CLR, Cap. 22 Resumo • Algoritmos elementares em grafos – Representação de grafos – Procura em Largura Primeiro • Breadth-First Search (BFS) – Propriedades da BFS – Procura em Profundidade Primeiro • Depth-First Search (DFS) – Propriedades da DFS – Ordenação Topológica – Componentes Fortemente Ligados • Strongly Connected Components (SCCs) – Exemplos 2003/2004 Análise e Síntese de Algoritmos 2 Grafos — Definição e Representação • Grafo definido por um conjunto V de vértices e um conjunto E de arcos, G = (V, E) – Arcos representam ligações entre pares de vértices • EVV – Grafo esparso: |E| << |V V| – Representação dos arcos • Matriz de adjacências: arcos representados por matriz – Para grafos densos • Listas de adjacências: arcos representados por listas – Para grafos esparsos • Grafos podem ser dirigidos ou não dirigidos – Existência (ou não) da noção de direcção nos arcos 2003/2004 Análise e Síntese de Algoritmos 3 Grafos — Definição e Representação • Listas vs. Matriz de adjacências Não Dirigido: 1 3 2 4 1 2 3 4 2 1 2 1 4 3 2 4 - 1 2 3 4 2 3 2 4 - - 1 2 3 4 1 0 1 0 1 2 1 0 1 1 3 0 1 0 0 4 1 1 0 0 1 2 3 4 1 0 0 0 0 2 1 0 0 1 3 0 1 0 0 4 1 0 0 0 Dirigido: 1 3 2 4 2003/2004 Análise e Síntese de Algoritmos 4 Grafos — Definição e Representação • Listas de adjacências: – Grafos não dirigidos • Tamanho das listas é 2 E – Grafos dirigidos • Tamanho das listas éE Tamanho total das listas de adjacências é O(V+E) • Grafos pesados: – Função de pesos: w: E R • Permite associar peso com cada arco 2003/2004 Análise e Síntese de Algoritmos 5 Procura em Largura Primeiro (BFS) • Dados G = (V, E) e vértice fonte s, BFS explora sistematicamente vértices de G para descobrir todos os vértices atingíveis a partir de s – Cálculo da distância: menor número de arcos de s para cada vértice atingível – Identificação de árvore BF: caminho mais curto de s para cada vértice atingível v • Fronteira entre nós descobertos e não descobertos é expandida uniformemente – Nós à distância k descobertos antes de qualquer nó à distância k+1 2003/2004 Análise e Síntese de Algoritmos 6 Procura em Largura Primeiro (BFS) • Implementação: – color[v]: cor do vértice v, branco, cinzento e preto – p[v]: predecessor de v na árvore BF – d[v]: tempo de descoberta de v • Outras definições: – d(s,v): menor distância de s a v • menor número de arcos em qualquer caminho de s para v 2003/2004 Análise e Síntese de Algoritmos 7 Procura em Largura Primeiro (BFS) • Algoritmo: function BFS(G,s) for each vertex u in V[G] - { s } inicializações color[u] = white; d[u] = ; p[u] = NIL color[s] = gray; d[s] = 0; p[s] = NIL Q={s} while Q u = Head[Q] ciclo for each v Adj[u] principal if color[v] = white color[v] = gray; d[v] = d[u] + 1; p[v] = u Enqueue (Q, v) Dequeue (Q) color[u] = black 2003/2004 Análise e Síntese de Algoritmos 8 Procura em Largura Primeiro (BFS) • Tempo de execução: O(V + E) – Inicialização: O(V) – Para cada vértice • Colocado na fila apenas 1 vez: • Lista de adjacências visitada 1 vez: O(V) O(E) • Exemplo 2003/2004 Análise e Síntese de Algoritmos 9 Procura em Largura Primeiro (BFS) • Resultado: – Para qualquer arco (u,v): ds, v ds,u 1 • Se u atingível, então v atingível – caminho mais curto para v não pode ser superior a caminho mais curto para u mais arco (u,v) • Se u não atingível, então resultado é válido (independentemente de v ser atingível) • … • No final da BFS: – d[u] = d(s,u), para todo o vértice u de V 2003/2004 Análise e Síntese de Algoritmos 10 Procura em Largura Primeiro (BFS) • Árvores BF: (sub-grafo de G) – Vértices atingíveis a partir de s – Arcos que definem a relação predecessor da BFS Gp Vp ,E p Vp v V : pV NIL s 2003/2004 E p pv , v E : v Vp s Análise e Síntese de Algoritmos 11 Procura Profundidade Primeiro (DFS) • Grafo pesquisado dando prioridade aos arcos dos vértices mais recentemente visitados • Resultado da procura: – Floresta DF: Gp V,Ep E p pv , v : v V pv NIL – Floresta DF composta por várias árvores DF • Implementação: – color[u]: cor do vértice (branco, cinzento, preto) – d[u]: tempo de início (de visita do vértice) – f[u]: tempo de fim (de visita do vértice) 2003/2004 Análise e Síntese de Algoritmos 12 Procura Profundidade Primeiro (DFS) • Algoritmo: function DFS(G) for each vertex u V[G] color[u] = white; p[u] = NIL time = 1 for each vertex u V[G] if color[u] = white DFS-Visit(u) function DFS-Visit(u) color[u] = gray; d[u] = time; time = time + 1 for each v Adj[u] if color[v] = white p[v] = u; DFS-Visit(v) color[u] = black; f[u] = time; time = time + 1 2003/2004 Análise e Síntese de Algoritmos 13 Procura Profundidade Primeiro (DFS) • Tempo de execução: O(V+E) – Inicialização: O(V) – Chamadas a DFS-Visit dentro de DFS: O(V) – Arcos analisados em DFS-Visit: (E) • Chamadas a DFS-Visit dentro de DFS-Visit: O(V) • Exemplo: 2003/2004 Análise e Síntese de Algoritmos 14 Procura Profundidade Primeiro (DFS) • Resultado: – Numa DFS de G = (V, E), para cada par de vértices u e v apenas um dos 3 casos seguintes é verdade: • Os intervalos [d[u], f[u]] e [d[v], f[v]] são disjuntos • [d[u], f[u]] está contido em [d[v], f[v]] e u é descendente de v na árvore DF • [d[v], f[v]] está contido em [d[u], f[u]] e v é descendente de u na árvore DF 1 d[v] d[u] v é descendente de u ( f[v] < f[u] ) f[u] f[v] d[v] intervalos são disjuntos f[u] 2003/2004 d[v] Análise e Síntese de Algoritmos 15 Procura Profundidade Primeiro (DFS) • Classificação de arcos (u,v): – Arcos de árvore: (tree edges) • arcos na floresta DF, Gp – (u,v) é arco de árvore se v foi visitado devido ao arco (u,v) ser visitado – Arcos para trás: (back edges) • ligam vértice u a vértice v antecessor na mesma árvore DF – Arcos para a frente: (forward edges) • ligam vértice v a vértice descendente na mesma árvore DF – Arcos de cruzamento: (cross edges) • Na mesma árvode DF, se u (ou v) não antecessor de v (ou u) • Entre árvores DF diferentes 2003/2004 Análise e Síntese de Algoritmos 16 Procura Profundidade Primeiro (DFS) • Classificação de cada arco (u,v): – Arco de árvore: • d[u] d[v] f[v] f[u] ; color[v] = white; visita v a partir de u – Arco para trás: • d[v] d[u] f[u] f[v] ; color[v] = gray – Arco para a frente: • d[u] d[v] f[v] f[u] ; color[v] = black – Arco de cruzamento: • d[v] f[v] d[u] f[u] ; color[v] = black 2003/2004 Análise e Síntese de Algoritmos 17 Procura Profundidade Primeiro (DFS) • Dado G = (V, E), não dirigido, cada arco é arco de árvore ou arco para trás – i.e., não existem arcos para a frente e de cruzamento • Numa floresta DFS, v é descendente de u se e só se quando u é descoberto existe um caminho de vértices brancos de u para v – v descendente de u existe caminho de vértices brancos de u para v • Qualquer vértice w descendente de u verifica [d[w], f[w]] [d[u], f[u]], pelo que w é branco quando u é descoberto – … 2003/2004 Análise e Síntese de Algoritmos 18 Recapitular • Representação de grafos – Listas de adjacências – Matrizes de adjacências • Procuras em grafos – BFS • Tempos de descoberta (d[]) – DFS • Tempos de início (d[]) e de fim (f[]) 2003/2004 Análise e Síntese de Algoritmos 19 Definições • Dado grafo G = (V, E), um caminho p é uma sequência <v0,v1,…,vk> tal que para todo o i, 0ik-1, (vi,vi+1)E • Se existe um caminho p de u para v,então v diz-se atingível a partir de u via p • Um ciclo num grafo G = (V,E) é um caminho <v0,v1,…,vk>, tal que v0 = vk • Um grafo dirigido G = (V,E) diz-se acíclico se não tem ciclos – Directed acyclic graph (DAG) 2003/2004 Análise e Síntese de Algoritmos 20 Ordenação Topológica • Uma ordenação topológica de um DAG G=(V,E) é uma ordenação de todos os vértices tal que se (u,v)E então u aparece antes de v na ordenação • Algoritmos: – Eliminação de vértices – Utilizando informação de DFS 2003/2004 Análise e Síntese de Algoritmos 21 Ordenação Topológica (Cont.) • Algoritmo: function Topological-Sort-1(G) L= // Lista de vértices Q= // Fila de vértices for each v G if v sem arcos de entrada (w,v) Enqueue(Q,v) while Q u = Head(Q) Eliminar todos os arcos (u,v) if v sem arcos de entrada (w,v) Colocar Enqueue(Q,v) vértices em L Dequeue(Q) Colocar u no fim da lista L O(V+E) 2003/2004 Análise e Síntese de Algoritmos Inicialização O(V) 22 Ordenação Topológica (Cont.) • Algoritmo: function Topological-Sort-2(G) Executar DFS(G) para cálculo do tempo de fim f[v] para cada v Para cada vértice terminado, inserir no princípio de lista ligada return lista ligada de vértices • Tempo de execução – DFS: O(V+E) • Exemplo 2003/2004 Análise e Síntese de Algoritmos 23 Ordenação Topológica (Cont.) • Intuição: 1 3 2 4 Na DFS: Tempo de fim de 3 é sempre Tempo de fim de 4 Tempo de fim de 2 é sempre Tempo de fim de 4 Tempo de fim de 1 é sempre Tempo de fim de 2,4 Sem ciclos, se existe caminho de u para v, verifica-se sempre f[u] f[v] ! 2003/2004 Análise e Síntese de Algoritmos 24 Componentes Fortemente Ligados • Definição: – Dado grafo dirigido G = (V,E) um componente fortemente ligado (SCC) é um conjunto máximo de vértices U V, tal que para u,vU, u é atingível a partir de v, e v é atingível a partir de u • Obs: vértice simples é SCC • Outras definições: – Grafo transposto de G = (V,E) • GT = (V, ET) tal que: E T u, v : v,u E – OBS: G e GT têm os mesmos SCCs 2003/2004 Análise e Síntese de Algoritmos 25 Componentes Fortemente Ligados • Algoritmo: function SCCs(G) Executar DFS(G) para cálculo do tempo de fim f[v] para cada v Representar GT Executar DFS(GT) (no ciclo principal de DFS considerar os vértices por ordem decrescente de tempo de fim de DFS(G)) Cada árvore de DFS encontrada corresponde a novo SCC • Tempo de execução: O(V+E) • Exemplo 2003/2004 Análise e Síntese de Algoritmos 26 Componentes Fortemente Ligados • Intuição: Em G: SCC 1 maior f Em GT: 2003/2004 SCC 2 maior f SCC 3 maior f SCC 1 SCC 2 SCC 3 árvore DFS árvore DFS árvore DFS Análise e Síntese de Algoritmos 27 Componentes Fortemente Ligados 1 G: 2 5 3 6 9 7 10 11 f[] = 24 4 GT: 4 max f > max f 8 1 2 2003/2004 max f > max f 12 5 3 6 9 7 8 Análise e Síntese de Algoritmos 10 11 12 28 Problemas • Algoritmo eficiente para determinar se grafo G = (V, E) é bipartido ? – Grafo G é bipartido se V pode ser dividido em L e R, tal que todos os arcos de G incidentes em 1 vértice de L e 1 vértice de R • Algoritmo eficiente para calcular o diâmetro de uma árvore T = (V, E) ? – Diâmetro: max du, v u,vV – Sol. 1: Duas BFSs – Sol. 2: Vértice adicional e 1 BFS 2003/2004 Análise e Síntese de Algoritmos 29 Outro Problema • Algoritmo eficiente para determinar se um grafo G=(V, E) é semi-ligado – Um grafo dirigido G = (V,E) diz-se semi-ligado se para qualquer par de vértices (u,v), u atingível a partir de v ou v atingível a partir de u 2003/2004 Análise e Síntese de Algoritmos 30 Revisão • Algoritmos elementares em grafos – Representação de grafos – BFS; DFS • Algoritmos • Propriedades – Aplicações: • Ordenação topológica • Componentes fortemente ligados • A seguir: – Estruturas de dados para conjuntos disjuntos (CLRS, Cap. 21) – Árvores abrangentes de menor custo (CLRS, Cap. 23) 2003/2004 Análise e Síntese de Algoritmos 31