Il DAG è una riduzione transitiva?


11

L'obiettivo di questa sfida è dato un grafico aciclico diretto finito (DAG), determinare se il grafico è una riduzione transitiva .

Una breve spiegazione di cosa sono un DAG e riduzioni transitive:

Un DAG è un grafico con bordi diretti (cioè è possibile viaggiare solo in una direzione su quel bordo) in modo tale che dato qualsiasi nodo iniziale sul grafico, è impossibile tornare al nodo iniziale (cioè non ci sono cicli).

Dato qualsiasi nodo iniziale, se è possibile viaggiare verso un altro nodo finale nel grafico tramite qualsiasi numero positivo arbitrario di bordi, quel nodo finale viene definito raggiungibile dal nodo iniziale. In un DAG generale, potrebbero esserci più percorsi che possono essere presi da un nodo iniziale a un nodo finale di destinazione. Ad esempio, prendi questo grafico a diamante:

inserisci qui la descrizione dell'immagine

Per accedere al nodo Dda A, è possibile prendere il percorso A->B->Do A->C->D. Pertanto, Dè raggiungibile da A. Tuttavia, non esiste alcun percorso che può essere preso per arrivare al nodo a Bpartire dal nodo C. Pertanto, il nodo Bnon è raggiungibile dal nodo C.

Definire la raggiungibilità del grafico come elenco di nodi raggiungibili per ogni nodo iniziale nel grafico. Quindi, per lo stesso esempio di grafico a diamante, la raggiungibilità è:

A: [B, C, D]
B: [D]
C: [D]
D: []

Un altro grafico che ha la stessa raggiungibilità del grafico sopra è mostrato di seguito:

inserisci qui la descrizione dell'immagine

Tuttavia, questo secondo grafico ha più spigoli rispetto al grafico originale. La riduzione transitiva di un grafico è un grafico con il minor numero di spigoli e la stessa raggiungibilità del grafico originale. Quindi il primo grafico è la riduzione transitiva del secondo.

Per un DAG finito, la riduzione transitiva è garantita ed è unica.

Ingresso

L'input è un "elenco di elenchi", in cui l'elenco esterno ha la lunghezza del numero di vertici e ogni elenco interno è la lunghezza del numero di spigoli che escono dal nodo associato e contiene gli indici dei nodi di destinazione. Ad esempio, un modo per descrivere il primo grafico sopra sarebbe (supponendo l'indicizzazione in base zero):

[[1, 2], [3], [3], []]

È possibile iniziare l'indicizzazione del primo nodo con qualsiasi valore intero arbitrario (ad es. Indicizzazione basata su 0 o 1).

L'ingresso può provenire da qualsiasi sorgente d'ingresso desiderata (stdio, parametro funzione, ecc.). Sei libero di scegliere il formato di input esatto purché non vengano fornite ulteriori informazioni. Ad esempio, se si desidera ottenere input da stdio, è possibile che ogni riga sia un elenco di spigoli per il nodo associato. Ex.:

1 2
3
3
'' (blank line)

Gli indici in ciascun elenco di adiacenza non sono necessariamente ordinati e potrebbero esserci più spigoli che collegano due nodi (es .:) [[1,1],[]]. Si può presumere che il grafico di input sia debolmente connesso e non contenga cicli (ovvero sia un DAG).

Produzione

L'output è veritiero se il DAG di input specificato è una riduzione transitiva e un valore falso in caso contrario. Questo può essere per qualsiasi sink desiderato (stdio, valore di ritorno, parametro di output, ecc.)

Esempi

Tutti gli esempi utilizzano l'indicizzazione basata su 0.

[[1,2],[3],[3],[]]
true

[[1,2,3],[3],[3],[]]
false

[[1,1],[]]
false

[[1,2,3,4],[5,6,7],[5,8,9],[6,8,10],[7,9,10],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
true

[[5,6,7],[2,3,0,4],[5,8,9],[6,8,10],[7,9,10],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
true

[[5,6,7],[2,3,0,4,14,5,7],[5,8,9],[6,8,10],[7,9,10],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
false

[[5,6,7],[2,3,0,4],[5,8,9],[6,8,10],[7,9,10,14],[11,12],[11,13],[12,13],[11,14],[12,14],[13,14],[],[],[],[]]
false

[[1,3],[2],[3],[]]
false

punteggio

Questo è il codice golf; vince il codice più piccolo in byte. Il codice dovrebbe essere completato in un ragionevole lasso di tempo (massimo 10 minuti su qualunque hardware tu abbia). Si applicano scappatoie standard. È possibile utilizzare qualsiasi componente incorporato desiderato.


Possiamo fare ipotesi sulla connettività dell'input? (Non ho controllato tutti i tuoi casi di test, ma coprono più parti disconnesse del grafico?)
Martin Ender

aggiornato con quello che credo sia la lingua corretta.
helloworld922,

Immagino che vada bene. Si potrebbe anche dire che il grafico è debolmente connesso .
Martin Ender,

Risposte:


5

Rubino, 101 97 byte

Approccio semplice che calcola la portata da ciascun nodo e considera se un nodo figlio può essere raggiunto tramite uno qualsiasi degli altri nodi. Apparentemente fallisce sui grafici ciclici, ma la definizione di un DAG implica che non dovrebbe essere comunque ciclico.

Provalo online!

->g{r=->i{i|i.map{|j|r[g[j]||[]]}.inject([],:|)}
g.all?{|e|e==e&e&&e.none?{|i|r[e-[i]].index i}}}

4

Mathematica, 95 82 byte

13 byte salvati grazie a @MartinEnder .

#~IsomorphicGraphQ~TransitiveReductionGraph@#&@Graph[x=0;##&@@Thread[++x->#]&/@#]&

Funzione anonima. Prende un elenco nidificato come input (basato su 1) e restituisce Trueo Falsecome output. La soluzione principale qui è il 46 byte #~IsomorphicGraphQ~TransitiveReductionGraph@#&, che verifica se un dato grafico è isomorfo alla sua riduzione transitiva. Il resto converte l'input in un Graphoggetto.


3

CJam (41 byte)

q~:A_,{{Af=e__&}%_}*]:.|A.&A:$:e`e_2%1-*!

Demo online , cablaggio di prova

Dissezione

q~:A      e# Parse input and store in A
_,{       e# Loop V times
  {       e#   Extend adjacency list representation of G^i to G^(i+1)
    Af=   e#   by extending each path by one edge
    e__&  e#   and flattening. NB :| would be shorter but breaks for empty lists
  }%
  _       e#   Duplicate, so that we build up G^2, G^3, ..., G^n
}*]       e# Gather in a single array
:.|       e# Fold pointwise union, giving the reachability from each vertex by
          e# paths of length > 1
A.&       e# Pointwise intersect with the paths of length 1
          e# We hope to get an array of empty arrays

          e# Handle the awkward special case of duplicate edges:
A:$       e# Sort each adjacency list
:e`       e# Run-length encode each adjacency list
e_2%      e# Extract only the run lengths
1-        e# Discard the 1s - so we now have an empty array unless there's a dupe

*         e# Join. We hope to be joining an array of empty arrays by an empty array
          e# giving an empty array
!         e# Check that we get a falsy value (i.e. the empty array)

3

Gelatina, 20 byte

ị³$ÐĿ€ị@Fœ&¥";œ-Q$€E

Utilizza l'indicizzazione basata su 1. Provalo online!

Panoramica generale

     €                for each vertex,
ị³$ÐĿ                   compute its reach.
        Fœ&¥"         intersect each vertex's lists of children and
      ị@                children's reaches.
             ;        then concatenate the list of intersections with
              œ-Q$€     all duplicate edges in the original graph.
                   E  are all elements equal? checks that all are empty lists,
                        meaning empty intersections and no duplicates.
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.