Algoritmos para Grafos | Índice
O conceito de componente forte
generaliza os conceitos de
componente conexa
e de componente aresta-biconexa.
Uma componente forte de um grafo é uma parte do grafo que tem forte coesão interna
mas fraca ligação
com o resto do grafo.
Para definir essa ideia com precisão,
usaremos as classes de equivalência da relação de
ligação forte.
Este capítulo trata do problema de encontrar as componentes fortes de um grafo. Esse problema é mais complexo que o problema das componentes conexas de grafos não-dirigidos, mas semelhante ao problema das componentes aresta-biconexas.
Dizemos que um vértice de um grafo é fortemente ligado a outro se um está ao alcance do outro e vice-versa. Essa ligação forte entre dois vértices é uma relação de equivalência, ou seja, uma relação reflexiva, simétrica, e transitiva. Cada classe de equivalência dessa relação induz um subgrafo fortemente conexo. Cada um desses subgrafos é uma componente forte (= strong component) do grafo. Podemos resumir essa definição dizendo que uma componente forte de um grafo é um subgrafo fortemente conexo maximal.
É claro que cada vértice de um grafo pertence a uma e uma só componente forte. É claro também que dois vértices pertencem à mesma componente forte se e somente se são fortemente ligados. Segue daí que todos os vértices de qualquer passeio fechado pertencem à mesma componente forte. Em particular, todos os vértices de qualquer ciclo pertencem à mesma componente forte.
Exemplo A. O grafo da figura [copiado do livro de Sedgewick e Wayne] tem cinco componentes fortes, indicadas pelas manchas cinza. Eis os conjuntos de vértices das cinco componentes:
7 8 6 9 10 11 12 0 2 3 4 5 1
Verifique que o subgrafo induzido por cada um desses conjuntos é fortemente conexo maximal.
0: 1 6 1: 2 5 2: 1 3 3: 4 4: 3 5: 2 6: 7 8 7: 3 6 9 8: 7 9:
0: 1 1: 2 2: 3 5 3: 4 4: 3 5: 1 3
Para exibir as componentes fortes de um grafo, podemos atribuir cores aos vértices de tal modo que todos os vértices da mesma componente tenham a mesma cor. Em outras palavras, podemos fazer uma numeração sc[0..V-1] dos vértices tal que sc[v] ≡ sc[w] se e somente se v e w estão na mesma componente forte. (O nome do vetor é uma abreviatura da expressão strong component.) Diremos que qualquer numeração com essa propriedade identifica as componentes fortes do grafo.
Como as diferentes componentes fortes de um grafo G estão ligadas umas às outras? O grafo das componentes fortes de G é o grafo D(G) definido assim: os vértices de D(G) são as componentes fortes de G e há um arco X-Y em D(G) se e somente se X é diferente de Y e algum arco de G sai de X e entra em Y.
É fácil verificar que o grafo D(G) é acíclico. Por isso, D(G) é às vezes chamado núcleo acíclico de G, ou dag das componentes fortes de G. Qualquer grafo pode ser visto como um dag em que cada vértice foi substituído por um grafo fortemente conexo.
Exemplo B. Cada componente forte de um dag tem um só vértice. Portanto, se G é um dag então D(G) é essencialmente igual a G.
Exemplo C. Considere novamente o grafo do exemplo A. A seguinte numeração dos vértices identifica as componentes fortes do grafo:
v 0 1 2 3 4 5 6 7 8 9 10 11 12 sc[v] 2 1 2 2 2 2 3 4 4 0 0 0 0
Os vértices do núcleo acíclico desse grafo são os subgrafos induzidos pelos seguintes conjuntos de vértices:
7 8 6 9 10 11 12 0 2 3 4 5 1
É um bom exercício listar os arcos do núcleo acíclico e verificar que o núcleo acíclico é um dag. (Note que a lista de vértices do núcleo apresentada há pouco está em ordem topológica.)
central. Digamos que um vértice v de um grafo é central se todos os vértices do grafo estão ao alcance de v. Esboce um algoritmo linear para encontrar todos os vértices centrais de um grafo.
popular. Digamos que um vértice w de um grafo é popular se estiver ao alcance de todos os outros vértices. Esboce um algoritmo linear para encontrar todos os vértices populares de um grafo.
Para vários problemas práticos em grafos,
a seguinte estratégia da colcha de retalhos
dá bons resultados:
primeiro, resolva o problema em cada componente forte do grafo;
depois, costure
as várias soluções parciais.
Por isso,
o seguinte problema é importante.
Problema das componentes fortes: Encontrar todas as componentes fortes de um grafo.
Para resolver o problema, poderíamos simplesmente calcular, para cada vértice v, todos os vértices fortemente ligados a v. Poderíamos até remover, preliminarmente, todos os arcos que não pertencem a ciclos, pois esses arcos não pertencem a componentes fortes. Mas os algoritmos baseados nessas ideias são muito lentos.
O ponto de partida de um algoritmo rápido para componentes fortes é uma busca em profundidade (veja o capítulo Busca DFS). É tentador imaginar que cada etapa de uma busca DFS revela uma das componentes fortes do grafo. Mas isso está longe de ser verdade, a menos que o vértice inicial de cada etapa sejam escolhido de uma maneira muito especial. (Por exemplo, se tivéssemos acesso ao grafo das componentes fortes e à lista de seus vértices em ordem anti-topológica, bastaria começar cada nova etapa da busca em qualquer vértice da próxima componente ainda não visitada da lista.)
Os próximos capítulos discutirão dois algoritmos eficientes para o problema das componentes fortes:
O algoritmo de Tarjan é assintoticamente tão eficiente quanto o algoritmo de Kosaraju, mas leva vantagem sobre esse último porque não exige a construção do grafo reverso e faz uma só busca em profundidade.