Quando il grafico diretto è lineare, restituire i nodi in ordine.Altrimenti fallire

cs.stackexchange https://cs.stackexchange.com/questions/125142

  •  29-09-2020
  •  | 
  •  

Domanda

il problema

Ho un set di edges (a, b), dove a e b sono nodi in un grafico aciclico diretto (DAG).

Il numero di bordi è garantito per essere il numero di nodi - 1.

Sto cercando un algoritmo che trova una sequenza di nodi [n_1, ... n_n] in modo che la sequenza contiene tutti i nodi nel grafico e che tutti i bordi (n_i, n_i+1) per 0 < i < n esistono in edges. Se quella sequenza non è possibile perché il set datato di edges non è uguale al set di bordi richiesti, allora ho bisogno di un errore da lanciare.

Modifica: il grafico potrebbe avere un numero arbitrario di componenti disconnessi. Ovviamente non considero un grafico con più componenti disconnessi come lineari.

Idee finora

Nota che sto controllando che il numero di generatoriTagCode sia esattamente il numero di bordi richiesti per tale sequenza di esistere. Di conseguenza, l'algoritmo può fallire quando ci sono due bordi che condividono una fonte o una destinazione. Tuttavia, ho ancora bisogno di ottenere quella sequenza.

Mi rendo conto che il tipo topologico restituisce un ordine lineare di un grafico diretto, che soddisfi le mie esigenze. Tuttavia, voglio ancora fallire quando il grafico non è esattamente lineare in quel modo, invece di ottenere comunque un ordine lineare.

Forse posso convalidare, quindi fai un tipo topologico. Ma questo sembra inefficiente. Inoltre non sono sicuro dei nomi formali delle cose in questo problema, quindi è difficile cercare semplicemente un algoritmo. Mi sento come se mi manca una semplice connessione o un trucco qui.

Potresti fornirmi un algoritmo che lo realizza? Prenderò pseudocode o qualsiasi lingua di tua scelta.

È stato utile?

Soluzione 2

Ho capito un algoritmo che passa almeno i miei casi di test:

let N = set of all nodes
let E = set of all edges

if (|E| != |N|-1) fail

let possibleStartNodes = new set containing all of N
let nexts = new dictionary from node -> node

foreach (prev, next) in E:
  if (next not in possibleStartNodes) fail 
  remove next from possibleStartNodes
  nexts[prev] = next
end foreach

if (|possibleStartNodes| != 1) fail

let currentNode = the one node in possibleStartNodes
let ordering = new list
ordering.push(currentNode)

while (nexts contains value for currentNode) 
  ordering.push(next)
  currentNode = next
end while

return ordering
.

$ o (n) $ sembra abbastanza ragionevole per me.Ci sono modi per migliorare?

Modifica: Apprezzerei tutti i suggerimenti sui termini tecnici corretti per i concetti che sto usando

Altri suggerimenti

Ecco un algoritmo abbastanza non ottimale, per iniziare.

Vai su tutti i bordi $ (a, b) $ . Per ogni bordo, vai di nuovo su tutti i bordi e controlla quante volte Viene visualizzato $ A $ . STOP Una volta scoperta $ A $ appare solo una volta (se questo non succede mai, rifiutare). Prenderemo $ n_1= a $ .

Vai di nuovo tutti i bordi, cercando il bordo unico $ (n_1, b) $ in cui $ n_1 $ appare. Take $ n_2= B $ .

Vai di nuovo tutti i bordi, cercando un bordo $ (n_2, c) $ in cui $ n_2 $ < / span> appare a sinistra (se non c'è tale bordo, rifiutare). Prendere $ n_3= c $ .

Continua in questo modo, trovare $ n_4, \ ldots, n_n $ .

Questo algoritmo funziona in $ o (n ^ 2) $ . Utilizzando l'hashing, dovresti essere in grado di migliorarlo a $ o (n) $ .

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a cs.stackexchange
scroll top