Componenti fortemente connesse


16

Due vertici distinti in un grafico diretto sono fortemente collegati se esiste un percorso nel grafico tra loro. Un componente fortemente connesso del grafico è un sottoinsieme del grafico in modo tale che ogni coppia di vertici distinti nel sottoinsieme sia fortemente connessa e l'aggiunta di altri vertici al sottoinsieme spezzerebbe questa proprietà.

La tua sfida è quella di separare un grafico nei suoi componenti fortemente connessi. In particolare, è necessario generare tutti gli SCC nel grafico.

I / O:

Come input, è possibile utilizzare un elenco di spigoli diretti, un elenco di adiacenza, una matrice di adiacenza o qualsiasi altro formato di input ragionevole. Chiedi se non sei sicuro. È possibile supporre che il grafico non abbia vertici totalmente disconnessi e che non vi siano contorni automatici, ma non è possibile fare ulteriori assunzioni. Se lo si desidera, è anche possibile prendere l'elenco di vertici come input, nonché il numero di vertici.

Come output, è necessario fornire un partizionamento dei vertici, come un elenco di elenchi di vertici, in cui ciascun elenco secondario è un componente fortemente connesso, oppure un'etichettatura di vertici, in cui ogni etichetta corrisponde a un componente diverso.

Se si utilizza un'etichettatura, le etichette devono essere vertici o una sequenza consecutiva di numeri interi. Questo per evitare di scaricare il calcolo nelle etichette.

Esempi:

Questi esempi prendono elenchi di spigoli, in cui ogni spigolo è diretto dalla prima alla seconda voce e le partizioni di output. Sei libero di utilizzare questo formato o un altro.

L'ingresso è sulla prima riga, l'output è sulla seconda riga.

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

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

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

[[1, 2], [2, 3], [2, 5], [2, 6], [3, 4], [3, 7], [4, 3], [4, 8], [5, 1], [5, 6], [6, 7], [7, 6], [8, 7], [8, 4]]
[[1, 2, 5], [3, 4, 8], [6, 7]]

Punteggio e restrizioni:

Le scappatoie standard sono vietate, come sempre. Inoltre, sono vietati gli incorporati che trattano specificamente componenti fortemente connessi.

Le soluzioni dovrebbero essere eseguite in non più di un'ora sugli esempi forniti. (Questo ha lo scopo di prevenire soluzioni esponenziali lente e nient'altro.)

Questo è il codice golf. Vince il minor numero di byte.


Quanto sono flessibili le etichette che assegniamo a un componente collegato? Ad esempio, l'elenco degli indici dei vertici in quel componente sarebbe un'etichetta valida?
xnor

@xnor Completamente flessibile. Dovrebbe corrispondere tramite test di uguaglianza / stringhe identiche.
Isaacg,

Il nostro formato di input grafico può contenere anche il numero di vertici e / o un elenco di etichette di vertici?
xnor

@xnor Sì a entrambi. Lo modificherò in.
Isaacg

Nell'ultimo caso di test, sto ottenendo che 8non è in un componente [3,4]perché non può solo ciascuno 6e 7(nessuno dei quali può raggiungerlo).
xnor

Risposte:


7

Python 2 utilizza numpy, 71 62 byte

import numpy
def g(M,n):R=(M+M**0)**n>0;print(R&R.T).argmax(0)

Accetta input come numpymatrice che rappresenta l'adiacenza e il numero di nodi. Produce un output come una numpymatrice di righe che etichetta ciascun vertice in base al numero di vertice più basso nel suo componente.

Per una matrice di adiacenza M, la potenza della matrice M**nconta il numero di npercorsi -passo da ciascun vertice iniziale a ciascun vertice finale. L'aggiunta dell'identità a Mvia M+M**0modifica la matrice di adiacenza per aggiungere un self-loop a ogni lato. Quindi, (M+M**0)**nconta al massimo percorsi di lunghezza n(con ridondanza).

Poiché ogni percorso ha una lunghezza al massimo n, il numero di nodi, qualsiasi punto da (i,j)cui è jpossibile raggiungere il vertice icorrisponde a una voce positiva di (M+M**0)**n. La matrice di raggiungibilità è quindi R=(M+M**0)**n>0, dove >0funziona all'ingresso.

Calcolo del entrywise andcome R&R.T, dov'è R.Til trasposizione, quindi fornisce una matrice che indica le coppie di vertici reciprocamente raggiungibili. La sua iriga è un vettore indicatore per vertici nello stesso componente fortemente connesso. Prendendo il suo argmaxdi ogni riga dà l'indice del primo Truein esso, che è l'indice del vertice più piccolo nel suo componente.


4

JavaScript (ES6), 125 byte

a=>a.map(([m,n])=>(e[m]|=1<<n|e[n],e.map((o,i)=>o&1<<m?e[i]|=e[m]:0)),e=[])&&e.map((m,i)=>e.findIndex((n,j)=>n&1<<i&&m&1<<j))

Prende un elenco di coppie dirette come argomento, mentre il risultato è una matrice per ciascun vertice che fornisce il primo vertice fortemente connesso ad esso, che a mio avviso conta come un'etichettatura valida. Ad esempio, con l'ingresso [[1, 2], [2, 3], [2, 5], [2, 6], [3, 4], [3, 7], [4, 3], [4, 8], [5, 1], [5, 6], [6, 7], [7, 6], [8, 7], [8, 4]]restituisce [, 1, 1, 3, 3, 1, 6, 6, 3](non vi è alcun vertice 0; i vertici 1, 2 e 5 hanno l'etichetta 1; 3, 4 e 8 hanno l'etichetta 3 mentre 6 e 7 hanno l'etichetta 6).


4

MATL , 26 22 byte

tnX^Xy+HMY^gt!*Xu!"@f!

Questo utilizza lo stesso approccio della risposta di @ xnor .

Funziona nella versione corrente (15.0.0) della lingua.

L'input è la matrice di adiacenza del grafico, con le righe separate da punti e virgola. Il primo e l'ultimo caso di test sono

[0 1 0 1; 0 0 1 0; 1 0 0 0; 0 0 0 0]

[0 1 0 0 0 0 0 0; 0 0 1 0 1 1 0 0; 0 0 0 1 0 0 1 0; 0 0 1 0 0 0 0 1; 1 0 0 0 0 1 0 0; 0 0 0 0 0 0 1 0; 0 0 0 0 0 1 0 0; 0 0 0 1 0 0 1 0]

Provalo online!

t     % implicitly input adjacency matrix. Duplicate
n     % number of elements
X^    % square root
Xy    % identity matrix of that size
+     % add to adjacency matrix
HM    % push size again
Y^    % matrix power
g     % convert to logical values (0 and 1)
t!*   % multiply element-wise by transpose matrix
Xu    % unique rows. Each row is a connected component
!     % transpose
"     % for each column
  @   %   push that column
  f!  %   indices of nonzero elements, as a row
      % end for each. Implicitly display stack contents

3

Pyth, 13 byte

.gu+Gs@LQG.{k

Dimostrazione , suite di test

L'input è un elenco di adiacenza, rappresentato come un dizionario che mappa i vertici con l'elenco dei vertici ai quali ha i bordi (i suoi vicini diretti). L'output è una partizione.

L'essenza del programma è che troviamo l'insieme di vertici che sono raggiungibili da ciascun vertice e quindi raggruppiamo i vertici per quegli insiemi. Eventuali due vertici nello stesso SCC hanno lo stesso insieme di vertici raggiungibili da loro, perché ciascuno è raggiungibile dall'altro e la raggiungibilità è transitiva. Tutti i vertici in componenti diversi hanno insiemi raggiungibili diversi, poiché nessuno dei due contiene l'altro.

Spiegazione del codice:

.gu+Gs@LQG.{k
                  Implicit: Q is the input adjacency list.
.g           Q    Group the vertices of Q by (Q is implicit at EOF)
  u       .{k     The fixed point of the following function, 
                  starting at the set containing just that vertex
   +G             Add to the set
     s            The concatenation of
      @LQG        Map each prior vertex to its directed neighbors
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.