Consideriamo le versioni più semplici di questi problemi in cui i bordi non sono ponderati.
Dato un grafico sol, controlla se sol ha un ciclo.
Dato un grafico sol e un numero K, controlla se sol ha almeno un ciclo di lunghezza K.
Il primo è semplice e può essere risolto utilizzando DFS. Il secondo è NP-difficile.
Diamo un'occhiata a un problema ancora più semplice:
Dato un grafico sol e due vertici S e t, controlla se esiste un percorso semplice da S per t in sol.
Dato un grafico sol e due vertici S e t e un numero k, controlla se esiste un percorso semplice da s per t in G di lunghezza almeno k.
Tutti questi problemi hanno lo stesso sapore. Quello in alto è facile mentre quello in basso è NP-difficile. Spiegherò la differenza per l'ultimo perché è più semplice ma la stessa spiegazione si applica alle altre coppie.
Il motivo per cui quelli migliori sono facili mentre quelli inferiori non lo sono è il risultato della struttura delle risposte a questi problemi.
Diamo prima un'occhiata al problema di trovare un percorso semplice e proviamo a risolverlo in modo ricorsivo. Se proviamo semplicemente a risolvere direttamente questo problema, dovremmo tenere traccia dei vertici che abbiamo usato finora:
SimplePath(s,t,G):= c'è un percorso da s per t in G.
SimplePath(s,t,G) se e solo se
s=t o per alcuni u∈G SimplePath(s,u,G−t) e ut∈G.
Se proviamo a risolvere il problema con questo ingenuo algoritmo ricorsivo ci vorrà tempo esponenziale:
ci sono esponenzialmente molte possibilità per l'insieme di vertici inutilizzati!
Dobbiamo essere più intelligenti.
Perché abbiamo avuto esponenzialmente molte possibilità? Dato che stavamo cercando di trovare un percorso semplice e di applicare questa condizione, dovevamo tenere traccia dei vertici non utilizzati.
OK, quindi lasciamo cadere questa condizione e vediamo dove possiamo ottenere:
Considera il problema di trovare un percorso (non necessariamente semplice) da s per t. Poiché il percorso non deve essere semplice, non è necessario tenere traccia dei vertici non utilizzati. In altre parole, il grafico non cambia nel tempo.
PathG(s,t):= c'è un percorso da s per t.
PathG(s,t) se e solo se
s=to
per alcuniu∈G PathG(s,t) e ut∈G.
Ma non abbiamo ancora finito. Il problema è che non sappiamo sePathG(s,u)
è un problema minore di PathG(s,t). Quindi questa soluzione ricorsiva potrebbe finire in un ciclo e non terminare mai.
Per evitare ciò, possiamo aggiungere un parametro aggiuntivo che assicura che il problema si riduca: il numero di spigoli nel percorso.
PathG(s,t,k):= c'è un percorso da s per t con al massimo k bordi.
PathG(s,t,k) se e solo se
k=0 e s=t o
k>0 e per alcuni u∈G PathG(s,u,k−1) e ut∈G.
Ora nota che c'è un percorso semplice da s per t se c'è un percorso da s per t con al massimo nbordi. In altre parole:
SimplePath(s,t,G) se e solo se PathG(s,t,n).
I punti essenziali qui sono:
Ogni percorso semplice (non banale) da s per t
consiste in un semplice percorso da s a qualche vertice u e un vantaggio ut.
Possiamo supporre che t non appare nel percorso semplice da s per u.
Non abbiamo bisogno di mantenere esplicitamente l'elenco dei vertici inutilizzati.
Queste proprietà ci consentono di avere una ricorsione intelligente
per l'esistenza di un semplice problema di percorso.
Ora, questi non si applicano al problema di trovare almeno un percorso di lunghezza k. Non sappiamo almeno ridurre il problema di trovare un semplice percorso di lunghezzak
a un sottoproblema più piccolo senza mantenere l'elenco dei vertici inutilizzati. Tali proprietà ci consentono di risolvere in modo efficiente l'esistenza del problema del percorso.
Quando un grafico non ha un ciclo negativo, ci consentono di risolvere al massimo l'esistenza di un percorso di lunghezza k problema e i problemi del percorso semplice più breve in modo efficiente.
Tuttavia non sostengono per l'esistenza di un percorso di lunghezza almeno k. Considera un grafico con3 vertici s,u,t.
w(su)=1000,w(st)=1000,w(ut)=10,w(tu)=10. Il percorso di lunghezza almeno1001 a partire dal s per t contiene u e il percorso di lunghezza almeno 1001 a partire dal s per u contiene t. Quindi non possiamo ridurre un'istanza del problema a un'istanza più piccola del problema senza fornire esplicitamente l'elenco dei vertici inutilizzati.
In altre parole, non conosciamo almeno una ricorsione intelligente per l'esistenza di un semplice percorso di lunghezza k problema mentre conosciamo una ricorsione intelligente per l'esistenza di un percorso semplice.
Tornando all'ultima parte della tua domanda, c'è un problema con il tuo argomento.
È vero che l'esistenza di un ciclo di lunghezza >k
può essere risolto in tempo polinomiale per qualsiasi fisso k (vale a dire knon fa parte dell'input). (Simile a come si può verificare se un grafico non ponderato ha un ciclo di lunghezzak
in tempo O(nk).)
Tuttavia quando k fa parte dell'input che non regge più poiché il tempo di esecuzione dipende k in un brutto modo.