Referência dos algoritmos
Pseudocódigo, invariantes e erros comuns de cada método implementado no estúdio, na mesma notação usada em sala. É exatamente essa formulação que a simulação executa passo a passo.
Busca em grafos
Busca em Profundidade
Escolhe sempre o vértice marcado mais recentemente alcançado, registrando tempo de descoberta TD e tempo de término TT.
Ideia central
Busca genérica em que, dentre todos os vértices marcados e incidentes a alguma aresta ainda não explorada, escolhe-se sempre o mais recentemente alcançado. Cada vértice recebe um tempo de descoberta TD[v] e um tempo de término TT[v], marcados por um contador global t.
Invariante
Os intervalos de vida I(v) = [TD[v], TT[v]] são encaixados ou disjuntos, nunca se cruzam parcialmente. O vértice w é descendente de v se e somente se I(w) está contido em I(v).
Requisitos do grafo
Erros comuns
- Em grafo não direcionado só existem arestas de árvore e de retorno; avanço e cruzamento só aparecem em grafo direcionado.
- Esquecer a condição w ≠ pai[v]: a aresta usada para chegar em v não é aresta de retorno.
- Toda aresta de retorno evidencia um ciclo no grafo original. Em grafo direcionado, ela é a única evidência necessária.
Inicialização / Chamada inicialt ← 0para todo vértice v ∈ V(G) façaTD[v] ← 0; TT[v] ← 0; pai[v] ← nuloenquanto existir algum vértice v tal que TD[v] = 0 efetuarExecutar Busca_Profundidade(v) // v é a raiz da buscaBusca_Profundidade(v) // grafo não direcionadot ← t + 1; TD[v] ← tpara todo vértice w ∈ Γ(v) façase TD[w] = 0 então // aresta de árvorepai[w] ← v; Executar Busca_Profundidade(w)senão se TT[w] = 0 e w ≠ pai[v] entãoVisitar aresta de retorno {v, w}t ← t + 1; TT[v] ← tBusca_Profundidade(v) // grafo direcionadopara todo vértice w ∈ Γ⁺(v) façase TD[w] = 0 então aresta de árvore (v, w); pai[w] ← v; ...senão se TT[w] = 0 então aresta de retorno (v, w)senão se TD[v] < TD[w] então aresta de avanço (v, w)senão aresta de cruzamento (v, w)
Busca em grafos
Busca em Largura
Escolhe sempre o vértice marcado menos recentemente alcançado, usando uma fila, e define o nível de cada vértice.
Ideia central
Busca genérica em que, dentre todos os vértices marcados e incidentes a alguma aresta ainda não explorada, escolhe-se sempre o menos recentemente alcançado, critério implementado por uma fila. Cada vértice recebe um índice L[v] (ordem de descoberta) e um nível[v] (distância à raiz em número de arestas).
Invariante
nível[w] = nível[pai[w]] + 1 para todo w ≠ raiz. Assim, no momento em que w é marcado, nível[w] já é a distância (número de arestas) entre a raiz da busca e w.
Requisitos do grafo
Erros comuns
- Marcar o vértice (atribuir L[w]) apenas quando ele sai da fila, e não quando entra: o mesmo vértice acabaria enfileirado várias vezes.
- Esquecer a condição L[w] > L[v] ao classificar arestas de irmão e de primo: ela garante que cada aresta seja explorada uma única vez.
- Em grafo ponderado, a busca em largura só devolve caminho de peso mínimo se todos os pesos forem iguais; ela minimiza o número de arestas, não o peso.
Inicialização / Chamada inicialt ← 0; Fila ← ∅para todo vértice v ∈ V(G) façaL[v] ← 0; nível[v] ← 0; pai[v] ← nuloenquanto existir algum vértice v tal que L[v] = 0 efetuart ← t + 1; L[v] ← t // v é a raiz da buscaFila.Insere(v)Executar Busca_Largura()Busca_Largura()enquanto not Fila.Vazia() efetuarv ← Fila.Remove()para todo vértice w ∈ Γ(v) façase L[w] = 0 então // aresta de árvore (ou pai)pai[w] ← v; nível[w] ← nível[v] + 1t ← t + 1; L[w] ← t; Fila.Insere(w)senão se nível[w] = nível[v] + 1 entãoVisitar aresta de tio {v, w}senão se nível[w] = nível[v] e pai[v] = pai[w] e L[w] > L[v] entãoVisitar aresta de irmão {v, w}senão se nível[w] = nível[v] e pai[v] ≠ pai[w] e L[w] > L[v] entãoVisitar aresta de primo {v, w}
Conectividade
Método de Kosaraju
Encontra os componentes fortemente conexos (f-conexos) com duas buscas em profundidade: uma em G e outra no grafo reverso Gᴿ.
Ideia central
Uma primeira busca em profundidade em G registra os tempos de término TT. A segunda busca, feita no grafo reverso Gᴿ e tomando os vértices em ordem decrescente de TT, produz uma floresta em que cada árvore é exatamente um componente fortemente conexo (f-conexo).
Invariante
A ordem decrescente de tempo de término garante que a busca em Gᴿ iniciada em um vértice nunca escapa do componente f-conexo a que ele pertence.
Requisitos do grafo
Erros comuns
- Esquecer de construir o grafo reverso Gᴿ antes da segunda busca.
- Percorrer a segunda busca na ordem crescente de TT em vez da decrescente.
- Confundir os três níveis de conectividade de um grafo direcionado conexo: s-conexo (grafo subjacente conexo), sf-conexo (para todo par, um alcança o outro) e f-conexo (todos mutuamente alcançáveis).
Método de Kosaraju1. Fazer busca em profundidade em G// salvar os tempos de término TT de cada vértice2. Construir o grafo reverso (ou transposto) Gᴿ// se (v, w) ∈ E(G) então (w, v) ∈ E(Gᴿ)3. Fazer busca em profundidade em Gᴿ tomando os vérticesem ordem decrescente de TTCada árvore da floresta de profundidade obtida no passo 3corresponde a um componente fortemente conexo de G.
Grafos eulerianos
Método de Fleury
Constrói um trajeto euleriano caminhando pelo grafo e evitando atravessar uma ponte enquanto houver outra aresta disponível.
Ideia central
Um grafo conexo é euleriano se e somente se todos os seus vértices tiverem grau par (Teorema de Euler), e semi-euleriano se existirem exatamente dois vértices de grau ímpar. O método caminha pelo grafo removendo as arestas percorridas e evita atravessar uma ponte enquanto houver outra opção.
Invariante
O trajeto construído nunca repete arestas e, ao evitar pontes, mantém as arestas restantes de G' conexas, garantindo que a caminhada só termine quando todas tiverem sido percorridas.
Requisitos do grafo
Erros comuns
- Atravessar uma ponte enquanto existe outra aresta disponível: as arestas do outro lado ficam inalcançáveis e o trajeto termina cedo.
- Começar por um vértice de grau par em grafo semi-euleriano: o trajeto precisa partir de um dos dois vértices de grau ímpar.
- Confundir com grafo hamiltoniano: euleriano passa por cada aresta uma vez (trajeto), hamiltoniano por cada vértice uma vez (caminho).
Método de Fleury1. se V(G) possuir 3 ou mais vértices de grau ímpar então PARE2. Seja G' = (V', E') tal que V' ← V(G) e E' ← E(G)3. Selecionar vértice inicial v ∈ V'(escolher v cujo grau seja ímpar, se houver)4. enquanto E' ≠ ∅ efetuara. se d(v) > 1 entãoSelecionar aresta {v, w} que não seja ponte em G'senãoSelecionar a única aresta {v, w} disponível em G'c. v ← w; E' ← E' − {v, w}// Caminhar de v para w e eliminar a aresta percorrida
Árvore geradora mínima
Método de Prim
Inclui vértices um a um: a cada passo acrescenta a aresta de menor peso entre V(T) e os vértices ainda não selecionados.
Ideia central
Constrói a AGM incluindo vértices, um a um, de forma gulosa. Partindo de uma raiz r, a cada passo acrescenta a aresta de menor peso com uma extremidade em V(T) (já selecionados) e a outra fora de V(T).
Invariante
A cada iteração, T = (V(T), E(T)) é uma árvore e está contida em alguma árvore geradora mínima de G.
Requisitos do grafo
Erros comuns
- Comparar o peso da aresta com a distância acumulada desde a raiz em vez do peso da própria aresta, o que transformaria Prim em Dijkstra.
- Aplicar Prim em grafo direcionado: o problema correto passa a ser o de arborescência de peso mínimo.
- Em grafo desconexo não existe árvore geradora: um grafo G possui árvore geradora se e somente se G for conexo.
Método de Prim1. Escolher um vértice qualquer r ∈ V(G) // raiz2. V(T) ← { r } // conj. de vértices selecionados3. E(T) ← ∅ // conj. de arestas da AGM4. enquanto V(T) ≠ V(G) efetuara. Encontrar a aresta {v, w} de menor peso tal quev ∈ V(T) e w ∉ V(T)b. Acrescentar w a V(T)c. Acrescentar {v, w} a E(T)Peso total: C(T) = Σ w , para e ∈ E(T)e
Árvore geradora mínima
Método de Kruskal
Inclui arestas, e não vértices: ordena as arestas por peso não decrescente e aceita cada uma que não forme ciclo com as já inseridas em E(T).
Ideia central
Constrói a AGM incluindo arestas, e não vértices como em Prim. Ordena as arestas em ordem não decrescente de peso e aceita, a cada iteração, a aresta de menor peso que não forme ciclo com as já inseridas em E(T).
Invariante
A cada iteração, T = (V(T), E(T)) é uma floresta geradora contida em alguma árvore geradora mínima de G.
Requisitos do grafo
Erros comuns
- Supor que bastam n − 1 iterações: são necessárias pelo menos n − 1, mas podem ser mais, pois arestas que formam ciclo precisam ser ignoradas.
- Aceitar uma aresta cujos extremos já estão ligados por arestas de E(T): ela fecharia um ciclo.
- Em grafo desconexo o resultado é uma floresta geradora mínima, não uma árvore geradora.
Método de Kruskal1. Ordenar as arestas em ordem não decrescente de peso:e₁, e₂, e₃, . . .2. V(T) ← V(G) // todos os vértices entram na AGM3. E(T) ← { e₁ }4. j ← 2 // aresta a ser analisada5. enquanto | E(T) | < | V(T) | − 1 efetuara. se a aresta e não forma ciclo com as arestas de E(T)jentão Acrescentar e a E(T)jb. j ← j + 1
Caminho mínimo
Método de Dijkstra
"Fecha" um vértice por iteração, sempre o de menor dist, e relaxa as arestas tensas que saem dele.
Ideia central
Resolve o problema de caminho mínimo a partir de uma única raiz s. Baseia-se no princípio da relaxação e "fecha" um vértice por iteração: escolhe o vértice ainda não fechado com o menor valor de dist e relaxa as arestas tensas que saem dele.
Invariante
Para todo v ∈ S, dist[v] já é o peso do caminho mínimo da raiz até v. Ao final, dist[ ] guarda os pesos dos caminhos mínimos; os caminhos em si são recuperados pela lista de predecessores pred[ ].
Requisitos do grafo
Erros comuns
- Aplicar o método em grafo com aresta de peso negativo: ele falha. Reponderar, adicionando uma constante a todas as arestas, também pode falhar.
- Reabrir um vértice que já pertence a S: uma vez fechado, seu dist não muda mais.
- Achar que dist[ ] devolve os caminhos: sem pred[ ] obtêm-se apenas os pesos.
Operação de relaxaçãose dist[v] + d < dist[w] então // aresta (v, w) está tensa?vwdist[w] ← dist[v] + dvwpred[w] ← vMétodo de Dijkstra1. para todo vértice v ∈ V(G) façadist[v] ← ∞; pred[v] ← nulo2. dist[s] ← 0 // s é a raiz da busca3. S ← ∅ // conjunto dos vértices fechados4. enquanto S ≠ V(G) efetuara. Escolher o vértice v ∉ S de menor dist[v]b. S ← S ∪ { v } // "fechar" o vértice vc. para todo vértice w ∈ Γ⁺(v) façase dist[w] > dist[v] + d então // aresta tensa?vwdist[w] ← dist[v] + dvwpred[w] ← v
Caminho mínimo
Método de Bellman-Ford
Programação dinâmica: examina todas as arestas a cada iteração, relaxando as que estiverem tensas, por |V(G)| − 1 iterações.
Ideia central
Calcula caminhos mínimos por programação dinâmica. Em vez de "fechar" um vértice por iteração, como Dijkstra, examina todas as arestas a cada iteração. Como qualquer caminho em um grafo com n vértices possui no máximo n − 1 arestas, n − 1 iterações bastam.
Invariante
Após a i-ésima iteração, dist[w] é no máximo o peso do menor caminho de s a w que usa até i arestas.
Requisitos do grafo
Erros comuns
- Se, em alguma iteração, nenhuma aresta estiver tensa, o algoritmo pode terminar: as iterações seguintes não trariam atualizações.
- Havendo ciclo de peso negativo entre s e t, não existe caminho mínimo entre eles; sem esse ciclo, o caminho mínimo é simples (não repete vértices).
- Aresta não direcionada com peso negativo já é, por si só, um ciclo de peso negativo.
Operação de relaxaçãose dist[v] + d < dist[w] então // aresta (v, w) está tensa?vwdist[w] ← dist[v] + dvwpred[w] ← vMétodo de Bellman-Ford1. para todo vértice v ∈ V(G) façadist[v] ← ∞; pred[v] ← nulo2. dist[s] ← 03. para i = 1, . . ., | V(G) | − 1 façapara cada (v, w) ∈ E(G) façase dist[w] > dist[v] + d então // aresta tensa?vwdist[w] ← dist[v] + dvwpred[w] ← vSe ainda houver aresta tensa após a última iteração,então existe um ciclo de peso negativo no grafo.
Caminho mínimo
Método de Floyd-Warshall
Caminhos mínimos entre todos os pares por programação dinâmica: a rodada k libera o vértice k como intermediário.
Ideia central
Programação dinâmica sobre o conjunto de vértices intermediários permitidos. Numerados os vértices de 1 a n, distᵏ[i, j] é a distância entre i e j usando como intermediários apenas os vértices de { 1, 2, . . ., k }.
Invariante
Ao final da rodada k, dist[i, j] é o peso do menor caminho de i a j que usa apenas { 1, . . ., k } como vértices intermediários; pred[i, j] guarda o penúltimo vértice desse caminho.
Requisitos do grafo
Erros comuns
- Trocar a ordem dos laços: k precisa ser o laço mais externo.
- Atualizar o predecessor com pred[i, k] em vez de pred[k, j]: pred[i, j] é o penúltimo vértice do caminho de i para j.
- Entrada negativa na diagonal, isto é, dist[i, i] < 0, indica ciclo de peso negativo.
Relaxação do comprimento dos caminhosdistᵏ[i, j] = min( distᵏ⁻¹[i, j],distᵏ⁻¹[i, k] + distᵏ⁻¹[k, j] )com dist⁰[i, j] = d se (i, j) ∈ E(G); ∞ caso contrário;ije dist⁰[i, i] = 0Método de Floyd-Warshall1. para i = 1, . . ., n façapara j = 1, . . ., n | j ≠ i façadist[i, j] ← ∞; pred[i, j] ← nulodist[i, i] ← 0; pred[i, i] ← i2. para toda aresta (i, j) ∈ E(G) façadist[i, j] ← d ; pred[i, j] ← iij3. para k = 1, . . ., n faça // cada possível intermediáriopara i = 1, . . ., n façapara j = 1, . . ., n façase dist[i, j] > dist[i, k] + dist[k, j] entãodist[i, j] ← dist[i, k] + dist[k, j]pred[i, j] ← pred[k, j]
Fluxo máximo
Método de Ford-Fulkerson
Enquanto existir algum caminho aumentante em G'(f), envia por ele o gargalo δ e atualiza a rede residual.
Ideia central
Enquanto existir caminho aumentante da fonte s ao sumidouro t na rede residual G′(f), envia-se por ele o máximo possível, o gargalo δ, e a rede residual é atualizada. As arestas reversas permitem desfazer envios anteriores.
Invariante
O fluxo f respeita sempre a condição de capacidade, 0 ≤ f(e) ≤ u(e), e a condição de conservação em todo nó interno. Pelo teorema do fluxo máximo e corte mínimo, ao final o valor do fluxo iguala a capacidade do corte s-t mínimo.
Requisitos do grafo
Erros comuns
- Esquecer de criar a aresta reversa na rede residual, o que impede desfazer envios feitos em iterações anteriores.
- Escolher caminhos aumentantes arbitrários: com capacidades irracionais o método pode não terminar. Escolher sempre o caminho aumentante com menos arestas (busca em largura) é o método de Edmonds-Karp.
- Assumir que o corte mínimo é qualquer corte: na solução ótima, S é o conjunto dos vértices alcançáveis a partir da fonte s na rede residual final.
Rede residual G′(f): V(G′) = V(G) e, para e = (v, w) ∈ E:se f(e) < u(e): aresta direta (v, w) com u (e) = u(e) − f(e)rse f(e) > 0: aresta reversa (w, v) com capacidade f(e)Método de Ford-Fulkerson1. para toda aresta e ∈ E(G) faça f(e) ← 02. Construir a rede residual G′(f)3. enquanto existir caminho aumentante P em G′(f) efetuara. δ ← min { u (e) | e ∈ P } // "gargalo" de Prb. para cada aresta (v, w) ∈ P façai. se (v, w) for aresta direta entãof(v, w) ← f(v, w) + δ // aumentar fluxoii. senãof(w, v) ← f(w, v) − δ // reduzir fluxoc. Atualizar a rede residual G′(f)
Fluxo máximo
Método de Edmonds-Karp
Implementação eficiente de Ford-Fulkerson: a cada iteração escolhe o caminho aumentante mais curto, obtido por busca em largura.
Ideia central
Implementação eficiente do método de Ford-Fulkerson: a cada iteração seleciona o caminho aumentante da rede residual que seja mais curto, isto é, que use o menor número de arestas. Esse caminho é encontrado por uma busca em largura.
Invariante
O comprimento do caminho aumentante escolhido nunca diminui de uma iteração para a seguinte. O número máximo de caminhos aumentantes é O(n·m) e cada um é encontrado em O(m), donde O(n·m²).
Requisitos do grafo
Erros comuns
- Usar busca em profundidade: volta-se ao método de Ford-Fulkerson genérico, que é apenas pseudopolinomial, O(m·f), com f igual ao valor do fluxo máximo.
- Na rede com duas arestas de capacidade 100 ligadas por uma de capacidade 1, a escolha arbitrária pode exigir 200 iterações; a escolha do caminho mais curto exige 2.
- Esquecer que o método foi publicado de forma independente por Dinitz (1970) e por Edmonds e Karp (1972).
Método de Edmonds-Karp1. para toda aresta e ∈ E(G) faça f(e) ← 02. Construir a rede residual G′(f)3. enquanto existir algum caminho aumentante P em G′(f) efetuara. Seja P o caminho aumentante em G′(f) com menor númerode arestas // obtido por busca em largurab. δ ← min { u (e) | e ∈ P }rc. para cada aresta (v, w) ∈ P façai. se (v, w) for aresta direta entãof(v, w) ← f(v, w) + δii. senãof(w, v) ← f(w, v) − δd. Atualizar a rede residual G′(f)
Fluxo máximo
Método de Dinic
A cada iteração constrói a rede em níveis GL a partir de G′(f) e determina nela um fluxo de bloqueio.
Ideia central
Em vez de aumentar um caminho por vez, constrói a rede em níveis GL a partir de G′(f) e determina nela um fluxo de bloqueio inteiro. Como o número de níveis cresce pelo menos uma unidade a cada iteração, existem no máximo n − 1 fluxos de bloqueio.
Invariante
dist(t) é estritamente crescente entre iterações, logo há no máximo n − 1 fluxos de bloqueio. Cada fluxo de bloqueio é obtido em O(n·m), donde O(n²·m).
Requisitos do grafo
Erros comuns
- Buscar caminhos fora de GL: só valem as arestas (v, w) com dist(w) = dist(v) + 1.
- Reconstruir a rede em níveis a cada caminho, e não a cada fluxo de bloqueio, pois é o fluxo de bloqueio completo que caracteriza uma iteração.
- Parar quando um caminho satura: o fluxo de bloqueio só termina quando não existir mais nenhum caminho de s a t em GL.
Rede em níveis GL: V(GL) = V(G′) e, para (v, w) ∈ E(G′):(v, w) ∈ E(GL) com capacidade u (e) se dist(w) = dist(v) + 1,rem que dist(v) é a menor distância geodésica de s até vFluxo de bloqueio fb: fluxo em GL tal que, mantidas apenas asarestas com capacidade maior que fb, não exista maiscaminho aumentante em GLMétodo de Dinic1. para toda aresta e ∈ E(G) faça f(e) ← 02. Construir a rede residual G′(f)3. Construir a rede em níveis GL a partir de G′(f)4. enquanto dist(t) < ∞ efetuara. Determinar um fluxo de bloqueio fb em GLb. Atualizar o fluxo f usando fbc. Atualizar a rede residual G′(f)d. Construir a rede em níveis GL a partir de G′(f)
Ordenação topológica
Método de Kahn
Determina a cada instante um vértice com grau de entrada zero, insere-o no fim do resultado e reduz o grau de entrada de seus sucessores.
Ideia central
Determina a cada instante um vértice sem arestas de entrada, isto é, com d⁻(v) = 0, e o insere no fim do resultado. Em vez de remover as arestas, mantém e atualiza um mapa M com o grau de entrada de cada vértice.
Invariante
Um vértice só entra na fila quando todos os seus predecessores já estão em Ordena_Top, portanto ord(v) < ord(w) para toda aresta (v, w) ∈ E(G).
Requisitos do grafo
Erros comuns
- Aplicar a grafo não direcionado ou com ciclo: não há como estabelecer relação de precedência, e a ordenação topológica não existe.
- Interpretar a fila vazia com vértices pendentes como erro: é exatamente assim que o método detecta a existência de ciclo.
- Supor que a ordenação é única: cada grafo acíclico direcionado pode ter várias ordenações topológicas válidas.
Método de Kahn1. para todo vértice v faça M[v] ← d⁻(v)2. Fila ← ∅; Ordena_Top ← ∅3. para todo vértice v tal que d⁻(v) = 0 façaFila.Insere(v)4. enquanto not Fila.Vazia() efetuara. v ← Fila.Remove()b. Ordena_Top.InsereNoFim(v)c. para todo vértice w ∈ Γ⁺(v) façai. M[w] ← M[w] − 1ii. se M[w] = 0 então Fila.Insere(w)5. Se todos os vértices forem processados, SUCESSO;caso contrário, existe um CICLO
Ordenação topológica
Ordenação topológica por busca em profundidade
Descrito por Tarjan em 1976: insere cada vértice no início do resultado somente depois de visitar todos os que dependem dele.
Ideia central
Alternativa baseada na busca em profundidade, descrita por Tarjan em 1976. Cada vértice é inserido no resultado somente após todos os que dependem dele, e a inserção é feita no início da lista, daí a ordem reversa.
Invariante
Quando v recebe marca permanente, todos os vértices alcançáveis a partir de v já estão em Ordena_Top. Como v é inserido no início, ele precede todos eles na ordenação.
Requisitos do grafo
Erros comuns
- Inserir no fim em vez do início: a ordenação sai invertida. A ordem correta é a reversa da ordem de inserção, equivalente à ordem decrescente de tempo de término.
- Não distinguir marca temporária de permanente: só a marca temporária reencontrada evidencia ciclo; a permanente indica um vértice já resolvido.
- Confundir com a floresta de profundidade comum: aqui o que importa é a ordem de término, não a árvore.
Método por Busca em Profundidade1. para todo vértice v faça Marca[v] ← 02. Ordena_Top ← ∅3. enquanto existir algum vértice v tal que Marca[v] = 0efetuar Visita(v)Visita(v)1. se Marca[v] ≠ 2 então // se v não for permanentea. se Marca[v] = 1 então CICLO // marca temporáriab. Marca[v] ← 1 // marca temporáriac. para todo vértice w ∈ Γ⁺(v) faça Visita(w)d. Marca[v] ← 2 // marca permanentee. Ordena_Top.InsereNoInicio(v)
Emparelhamento
Método de Edmonds
Busca caminhos M-aumentantes entre vértices expostos, contraindo os botões (blossoms) que aparecem, até que não exista mais nenhum.
Ideia central
Pelo teorema de Berge, M tem cardinalidade máxima se e somente se não existe caminho M-aumentante. O método busca esses caminhos em uma floresta M-alternante; quando uma aresta liga dois vértices a distância par da mesma árvore, surge um ciclo ímpar, o botão (blossom), que é contraído em um pseudovértice.
Invariante
M ⊕ EP é sempre um emparelhamento com uma aresta a mais que M. Pelo teorema de Edmonds, M é máximo em G se e somente se M/B é máximo em G/B, o que legitima a contração dos botões.
Requisitos do grafo
Erros comuns
- Usar apenas busca em largura ou profundidade em grafo genérico: sem tratar os botões, caminhos M-aumentantes existentes deixam de ser encontrados.
- Ignorar a aresta {v, w} quando dist(w, F.raiz[w]) for ímpar: ela não gera caminho aumentante.
- Confundir emparelhamento maximal com máximo: maximal apenas não admite acrescentar arestas; máximo é o de maior cardinalidade. E emparelhamento máximo não implica casamento perfeito.
Emparelhamento_Máximo(G)1. M ← ∅2. P ← Encontra_Caminho_Aumentante(G, M)3. enquanto (P ≠ ∅) efetuara. M ← M ⊕ EPb. P ← Encontra_Caminho_Aumentante(G, M)Encontra_Caminho_Aumentante(G, M)1. F ← Inicializa_Floresta_Alternante(G, M)2. para todo vértice desmarcado v ∈ F tal quedist(v, F.raiz[v]) for par façaa. enquanto ∃ aresta e = {v, w} desmarcada efetuari. se w ∉ F então Adicionar_a_Floresta(M, F, v, w)ii. senão se dist(w, F.raiz[w]) for par entãoretornar Obter_Novo_Caminho(G, M, F, v, w)iii. Marcar aresta eb. Marcar vértice v3. retornar ∅Obter_Novo_Caminho(G, M, F, v, w)1. se F.raiz[v] ≠ F.raiz[w] entãoP ← ObterCaminho(F, F.raiz[v], v)+ ObterCaminho(F, w, F.raiz[w])2. senão // botão (blossom)a. B ← ObterCaminho(F, v, w) + vb. G′ ← Contrair_Blossom_Grafo(G, B, z)c. M′ ← Contrair_Blossom_Emparelhamento(M, B, z)d. P ← Encontra_Caminho_Aumentante(G′, M′)e. se z ∈ P então P ← Expandir_Blossom(P, G, B, z)3. retornar P
Coloração
Método guloso
Percorre os vértices em uma ordem qualquer e atribui a cada um a cor de menor índice não utilizada por nenhum de seus vizinhos.
Ideia central
Não há método eficiente para obter a coloração mínima de um grafo, mas é possível obter rapidamente uma coloração aproximada: percorrem-se os vértices em uma ordem qualquer, atribuindo a cada um a cor de menor índice não utilizada por seus vizinhos.
Invariante
A cada passo a coloração parcial é válida: cor(v) ≠ cor(w) para todo par de vértices adjacentes já coloridos. Como um vértice tem no máximo Δ(G) vizinhos, o método nunca usa mais que Δ(G) + 1 cores.
Requisitos do grafo
Erros comuns
- Tomar o número de cores obtido como o número cromático: o resultado depende da ordem dos vértices e em geral χ(G) é menor.
- Esquecer os limites conhecidos: ω(G) ≤ χ(G) ≤ Δ(G) + 1 e, pelo Teorema de Brooks, χ(G) ≤ Δ(G) se G for simples, não completo e não for ciclo ímpar.
- Aplicar a grafo direcionado: a coloração de vértices é definida para grafo não direcionado.
Método Guloso1. Considerar os vértices do grafo em uma ordem qualquerv₁, v₂, . . ., vₙ2. Identificar as cores com índices, adicionando mais coresquando necessário3. Colorir v₁ com a primeira cor4. A cada iteração, atribuir ao vértice corrente a cor demenor índice não utilizada por nenhum de seus vizinhos
Coloração
Método de Welsh-Powell
Ordena os vértices em ordem não crescente de graus e colore, com uma mesma cor, todos os que não estiverem conectados a um vértice já colorido com ela.
Ideia central
Refinamento do método guloso: os vértices são ordenados em ordem não crescente de graus e cada cor é distribuída em uma passagem completa pela lista, colorindo todos os vértices que não estejam conectados a um já colorido com aquela cor.
Invariante
Cada cor forma um conjunto independente: nenhum par de vértices que recebem a mesma cor é adjacente. O método termina porque cada passagem colore pelo menos um vértice.
Requisitos do grafo
Erros comuns
- Tomar o resultado como ótimo: existe contraexemplo em que Welsh-Powell usa 3 cores num grafo bipartido, para o qual χ(G) = 2.
- Abandonar a ordem por grau ao iniciar uma nova cor: a lista ordenada é percorrida do começo em cada passagem.
- Colorir um vértice adjacente a outro já colorido com a cor da passagem atual: a verificação é contra os vértices já coloridos com aquela cor.
Método de Welsh-Powell1. Ordenar os vértices em ordem não crescente de grausv₁, v₂, . . ., vₙ2. Identificar as cores com índices, adicionando mais coresquando necessário3. Colorir v₁ com a primeira cor4. Seguir pela lista de vértices colorindo todos os vérticesnão conectados a um vértice já colorido, usando semprea mesma cor5. Repetir o passo 4 para todos os vértices não coloridosusando uma nova cor, sempre respeitando a ordem nãocrescente de graus, até que todos estejam coloridos