Diretto sindacato-trova


11

Considera un grafico diretto su cui puoi aggiungere dinamicamente i bordi e fare alcune domande specifiche.G

Esempio: foresta disgiunta

Considera il seguente set di query:

arrow(u, v)
equiv(u, v)
find(u)

il primo aggiunge una freccia al grafico, il secondo decide se , l'ultimo trova un rappresentante canonico della classe di equivalenza di , ovvero una tale che implica .u v r ( u ) u v r ( v ) = r ( u )uvuvr(u)uvr(v)=r(u)

Esiste un noto algoritmo che utilizza la struttura di dati forestali disgiunti che implementa queste query in complessità ammortizzata quasi costante, vale a dire O(α(n)) . Si noti che in questo caso equivviene implementato utilizzando find.

Variante più complessa

Ora sono interessato a un problema più complesso in cui le indicazioni contano:

arrow(u, v)
confl(u, v)
find(u)

il primo aggiunge una freccia , i secondi decidono se esiste un nodo raggiungibile sia da che da , cioè . L'ultimo dovrebbe restituire un oggetto tale che implica dove dovrebbe essere facilmente calcolabile. (Per, diciamo, calcola ). L'obiettivo è trovare una buona struttura di dati in modo che queste operazioni siano veloci.uvwuvuvr(u)uvr(u)r(v)confl

cicli

Il grafico può contenere cicli.

Non so se esiste un modo per calcolare in modo efficiente e incrementale i componenti fortemente connessi, al fine di considerare solo i DAG per il problema principale.

Naturalmente apprezzerei anche una soluzione per i DAG. Corrisponderebbe a un calcolo incrementale dell'antenato meno comune.

Approccio ingenuo

La struttura di dati della foresta disgiunta non è utile qui, poiché ignora la direzione dei bordi. Si noti che non può essere un singolo nodo, nel caso in cui il grafico non sia confluente.r(u)

Si può definire e definire come quando . Ma come calcolare questo in modo incrementale?r(u)={vuv}S1S2S1S2

Probabilmente che il calcolo di un set così grande non è utile, un set più piccolo dovrebbe essere più interessante, come nel solito algoritmo di ricerca unione.

Risposte:


3

( Modifica : riscrivo completamente la mia risposta ora che la mia comprensione del problema è (spero) più chiara.)

Sembra che questo problema possa essere ridotto alla costruzione e al miglioramento incrementali di un'approssimazione della chiusura transitiva del grafico, poiché il grafico viene creato e cercato.

r(u) è, astrattamente, l'insieme di tutti i nodi che sono raggiungibile sia e per ogni nel grafico. (Naturalmente, non tutte le coppie avranno necessariamente un nodo che può essere raggiunto da entrambi.) A differenza del caso in union-find, questo set non può essere rappresentato come un nodo rappresentativo canonico nel grafico, perché possono esserci nodi raggiungibili sia da che da , sia da che da , che non sono tuttavia raggiungibili sia da che da .uvvuu,vuvuwvw

Diciamo che mantenere, per ogni , un insieme di nodi raggiungibile da (I chiameremo ). Questi insiemi sarebbero necessariamente una struttura di dati extra per ciascun nodo, o almeno un insieme di spigoli di "scorciatoia" extra nel grafico. Se non ti interessa conservare la struttura del grafico specificata, non sarebbe necessario distinguere tra questi bordi e i bordi specificati.uuR(u)

Non ho idee per una struttura di dati che catturi ciò che è più efficiente del caso generale (ad esempio un vettore bit o una tabella hash), ma è possibile aggiornare questi set in modo incrementale:

Ogni volta che aggiungi un bordo da ad un altro nodo , imposti .uvR(u)=R(u)R(v)

Implementare conflprima provando ; se non è vuoto, restituire true. Ma se è vuoto, fai due ricerche parallele in ampiezza da e fino a esaurire entrambi gli insiemi raggiungibili o trovare un nodo in comune. Mentre lo fai, aggiorna anche e (e le di tutti i nodi intermedi che trovi) per includere i nodi raggiungibili che hai trovato. e se trovi un nodo in comune, imposta R (u) = R (v) = R (u) \ cup R (v) .R(u)R(v)R(u)R(v)R(u)R(v)R

find(u)restituisce solo . Il problema è che non è implementato solo in termini di . Non vedo come potrebbe essere, a meno che l'algoritmo non fosse non incrementale (ovvero pre-calcolare tutti gli insiemi di tutti i nodi con la chiusura transitiva del grafico). Tuttavia, l'approccio incrementale dovrebbe comunque fornire un buon ammortamento costo, anche se non ho idea se si avvicina alla mano . (Probabilmente no. Una risposta falsa da richiede che tu avvii due BFS anche quando i tuoi set sono saturi; anche questo sembra inevitabile a meno che l'algoritmo non sia reso non incrementale.)R(u)conflfindRO(α(n))conflR

Sembra un po 'come un caso speciale dei metodi di La Poutré e van Leeuwen per mantenere la chiusura transitiva di un grafico .

Mi rendo conto che questo non risponde completamente alla domanda, ma forse serve a chiarirlo, e qualcuno che ha più esperienza con gli algoritmi grafici può fornire una migliore struttura di dati per codificare i setR


Grazie per la tua risposta, spero di aver chiarito la mia domanda ora: non mi importa dei componenti collegati (ma i CC fortemente potrebbero essere utili alla soluzione finale); Non ho ancora e questo non può essere un singolo nodo in un DAG. r(u)r(u)
jmad,

OK, è un po 'più chiaro. Sembrerebbe che è, astrattamente, l'insieme di tutti i nodi che sono raggiungibili da entrambi e per ogni nel grafico. Questo insieme potrebbe essere un insieme di archi "scorciatoia" al largo di , penso, e poi questo comincia a guardare come calcolare la chiusura transitiva della raggiungibilità nel grafico. Non riesco ancora a capire immediatamente perché questo non possa essere fatto in modo incrementale (comprimere i percorsi quando li trovi) anche se probabilmente richiederebbe più spazio di archiviazione / lavoro (etichetta / aggiornamento di tutti i bordi dei "collegamenti") rispetto a union-find. ha senso? r(u)uv vuu
Chris Pressey,

Supponendo che la chiusura transitiva sia un modo equo di caratterizzare , sembra che sarebbe strettamente correlato: en.wikipedia.org/wiki/…r(u)
Chris Pressey,

Non credo che confl(u,v)dovrebbero unire e . Potrebbe modificarli, ma ciò sarebbe già stato fatto dalla chiamata a , come nel metodo foresta disgiunto. R(u)R(v)find
jmad

Hai ragione che non dovrebbe unirli; Modificherò la risposta. Ma le chiamate a finddavvero non possono calcolare nulla di utile, perché non esiste un oggetto unico da "trovare" tranne , che approssima. (Come sarebbe sapere cosa cercare, per rendere gli aggiornamenti Si è dato solo? ma le informazioni in si applica potenzialmente ad ogni altro nodo del grafo.)r(u)R(u)finduR(u)
Chris Pressey
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.