Algoritmos para Grafos, via Sedgewick | Índice remissivo
Muitos problemas básicos sobre digrafos admitem solução bem mais eficiente se restringirmos nosso universo aos DAGs (ou melhor, a digrafos dotados de ordenação topológica). Frequentemente as soluções usam algoritmos de programação dinâmica (veja os apontadores para "programação dinâmica" na página Análise de Algoritmos).
(Esta página corresponde aproximadamente à seção 19.6 (Topological Sorting) do capítulo 19 (Digraphs and DAGs), p.183-193, do livro de Sedgewick.)
Suponha que G é um DAG com custos não negativos nos arcos. Sejam s e t dois vértices de G. Para encontrar um caminho de custo mínimo de s a t, podemos usar o algoritmo de Dijkstra, que ignora o caráter acíclico de G. Esse algoritmo consome tempo proporcional a (V+A) log(V) no pior caso (e é, portanto, um pouco pior que linear). Se tirarmos proveito do caráter acíclico de G, é possível resolver o problema em tempo linear, ou seja, tempo limitado por
V + A
no pior caso. A função abaixo faz isso. Se não existe caminho algum de s a t, a função devolve um número maxCOST que faz o papel de ∞.
/* A função DAGmin recebe um DAG G com custos não negativos nos arcos e uma ordenação topológica ts de G. Recebe também um vértice s. Para cada vértice t, a função calcula o custo de um caminho de custo mínimo de s a t. Esse número é depositado em cost[t]. */
/* A função supõe que a soma dos custos de todos os arcos é estritamente menor que maxCOST. (O código é uma versão modificada do programa 21.6, p.304, Sedgewick.) */
void DAGmin (Digraph G, Vertex ts[], Vertex s, double cost[]) { int i; Vertex v; link p; for (v = 0; v < G->V; v++) cost[v] = maxCOST; cost[s] = 0.0; for (v = ts[i = 0]; i < G->V; v = ts[i++]) for (p = G->adj[v]; p != NULL; p = p->next) if (cost[p->w] > cost[v] + p->cost) cost[p->w] = cost[v] + p->cost; }
Do ponto de vista computacional, o problema de encontrar um caminho simples de custo máximo num digrafos com custos nos arcos é difícil. O problema torna-se fácil, entretanto, quando restrito a DAGs.
Dados vértices s e t de um DAG com custos não negativos nos arcos, considere o problema de encontrar um caminho simples de custo máximo de s a t. (Na verdade, o requisito "simpes" é redundante, pois todos os caminhos num DAG são simples.) A função abaixo resolve o problema. Compare o código com o de DAGmin.
/* A função DAGmax recebe um DAG G com custos não negativos nos arcos e uma ordenação topológica ts de G. Recebe também um vértice s. Para cada vértice t, a função calcula o custo de um caminho de custo máximo de s a t. Esse número é depositado em cost[t]. */
/* A função supõe que a soma dos custos de todos os arcos é estritamente menor que maxCOST. (O código é uma versão modificada do programa 21.6, p.304, Sedgewick, que define a função DIGRAPHlpt.) */
void DAGmax (Digraph G, Vertex ts[], Vertex s, double cost[]) { int i; Vertex v; link p; for (v = 0; v < G->V; v++) cost[v] = -maxCOST; cost[s] = 0.0; for (v = ts[i = 0]; i < G->V; v = ts[i++]) for (p = G->adj[v]; p != NULL; p = p->next) if (cost[p->w] < cost[v] + p->cost) { cost[p->w] = cost[v] + p->cost; }
int maxpath (Digraph G) {
Vertex v;
link p;
int cost[maxV], x = 0;
for (v = 0; v < G->V; v++) cost[v] = 0;
for (v = 0; v < G->V; v++)
for (p = G->adj[v]; p != NULL; p = p->next) {
cost[p->w] = cost[v] + 1;
if (x < cost[p->w]) x = cost[p->w];
}
return x;
}