Vamos considerar as versões mais simples desses problemas em que as arestas não são ponderadas.
Dado um gráfico Gverifique se G tem um ciclo.
Dado um gráfico G e um número kverifique se G tem um ciclo de duração pelo menos k.
O primeiro é fácil e pode ser resolvido usando o DFS. O segundo é NP-difícil.
Vejamos um problema ainda mais simples:
Dado um gráfico G e dois vértices s e t, verifique se existe um caminho simples de s para t no G.
Dado um gráfico G e dois vértices s e t e um número k, verifique se existe um caminho simples de s para t no G de comprimento pelo menos k.
Todos esses problemas são do mesmo sabor. O superior é fácil, enquanto o inferior é NP-hard. Vou explicar a diferença para o último porque é mais simples, mas a mesma explicação se aplica aos outros pares.
A razão pela qual as primeiras são fáceis, enquanto as inferiores não são, é o resultado da estrutura das respostas para esses problemas.
Vamos primeiro examinar o problema de encontrar um caminho simples e tentar resolvê-lo recursivamente. Se apenas tentarmos resolver esse problema diretamente, precisaremos acompanhar os vértices que usamos até agora:
SimplePath(s,t,G):= existe um caminho de s para t no G.
SimplePath(s,t,G) iff
s=t ou para alguns u∈G SimplePath(s,u,G−t) e ut∈G.
Se tentarmos resolver o problema com esse ingênuo algoritmo recursivo, levará um tempo exponencial:
existem exponencialmente muitas possibilidades para o conjunto de vértices não utilizados!
Temos que ser mais inteligentes.
Por que obtivemos exponencialmente muitas possibilidades? Como estávamos tentando encontrar um caminho simples e impor essa condição, precisávamos acompanhar os vértices não utilizados.
OK, então vamos abandonar essa condição e ver onde podemos obter:
Considere o problema de encontrar um caminho (não é necessário simples) de s para t. Como o caminho não precisa ser simples, não precisamos rastrear vértices não utilizados. Em outras palavras, o gráfico não muda com o tempo.
PathG(s,t):= existe um caminho de s para t.
PathG(s,t) iff
s=tou
para algunsu∈G PathG(s,t) e ut∈G.
Mas nós ainda não acabamos. A questão é que não sabemos sePathG(s,u)
é um problema menor que PathG(s,t). Portanto, essa solução recursiva pode terminar em um loop e nunca terminar.
Para evitar isso, podemos adicionar um parâmetro extra que garanta que o problema fique menor: o número de arestas no caminho.
PathG(s,t,k):= existe um caminho de s para t com no máximo k arestas.
PathG(s,t,k) iff
k=0 e s=t ou
k>0 e para alguns u∈G PathG(s,u,k−1) e ut∈G.
Agora observe que existe um caminho simples de s para t se houver um caminho de s para t com no máximo narestas. Em outras palavras:
SimplePath(s,t,G) iff PathG(s,t,n).
Os pontos essenciais aqui são:
Todo caminho simples (não trivial) de s para t
consiste em um caminho simples de s para algum vértice u e uma vantagem ut.
Podemos assumir que t não aparece no caminho simples de s para u.
Não precisamos manter explicitamente a lista de vértices não utilizados.
Essas propriedades nos permitem ter uma recursão inteligente
pela existência de um problema de caminho simples.
Agora, isso não se aplica ao problema de encontrar um caminho de comprimento pelo menos k. Não sabemos como reduzir o problema de encontrar pelo menos um caminho simples de comprimentok
para um subproblema menor sem manter a lista de vértices não utilizados. Essas propriedades nos permitem resolver a existência do problema do caminho com eficiência.
Quando um gráfico não tem um ciclo negativo, ele nos permite resolver a existência de um caminho de comprimento, no máximo k problema e o menor caminho simples problemas com eficiência.
No entanto, eles não sustentam a existência de um caminho de comprimento pelo menos k. Considere um gráfico com3 vértices s,u,t.
w(su)=1000,w(st)=1000,w(ut)=10,w(tu)=10. O caminho do comprimento pelo menos1001 de s para t contém u e o caminho de comprimento pelo menos 1001 de s para u contém t. Portanto, não podemos reduzir uma instância do problema para uma instância menor do problema sem fornecer explicitamente a lista de vértices não utilizados.
Em outras palavras, não sabemos uma recursão inteligente para a existência de um caminho simples de comprimento pelo menos k problema enquanto conhecemos uma recursão inteligente pela existência de um caminho simples.
Voltando à última parte da sua pergunta, há um problema com o seu argumento.
É verdade que a existência de um ciclo de duração >k
pode ser resolvido em tempo polinomial para qualquer fixo k (ie knão faz parte da entrada). (Semelhante a como se pode verificar se um gráfico não ponderado tem um ciclo de duraçãok
em tempo O(nk).)
No entanto, quando k faz parte da entrada, isso não se sustenta mais, já que o tempo de execução depende de k de um jeito ruim.