Ho difficoltà a trovare un modo per classificare correttamente i bordi mentre una ricerca in ampiezza su un grafico diretto.Classificazione del bordo durante la ricerca di ampiezza su un grafico diretto
Durante una breadth-first o in profondità di ricerca, è possibile classificare i bordi sono incontrati con 4 classi:
- ALBERO
- INDIETRO
- CROSS
- AVANTI
Skiena [1] dà un'implementazione. Se ti sposti lungo un bordo da v1 a v2, ecco un modo per restituire la classe durante un DFS in java, come riferimento. La mappa dei genitori restituisce il vertice padre per la ricerca corrente e il metodo timeOf()
, l'ora in cui il vertice è stato scoperto.
if (v1.equals(parents.get(v2))) { return EdgeClass.TREE; }
if (discovered.contains(v2) && !processed.contains(v2)) { return EdgeClass.BACK; }
if (processed.contains(v2))
{
if (timeOf(v1) < timeOf(v2))
{
return EdgeClass.FORWARD;
}
else
{
return EdgeClass.CROSS;
}
}
return EdgeClass.UNCLASSIFIED;
Il mio problema è che non riesco a farlo bene per un ricerca in ampiezza su un grafo orientato. Per esempio:
Il grafico - che è un loop - è ok:
A -> B
A -> C
B -> C
BFSing da A, B sarà scoperta, poi C. I bordi EAB e PAO sono archi d'albero, e quando eBC viene incrociato per ultimo, B e C vengono elaborati e scoperti e questo margine è correttamente classificato come CROCE.
Ma un ciclo semplice non funziona:
A -> B
B -> C
C -> A
Quando il bordo ECA è attraversato ultimo, A viene elaborato e scoperto. Quindi questo bordo è etichettato erroneamente come CROCE, se dovrebbe essere un bordo posteriore.
Non c'è davvero alcuna differenza nel modo in cui i due casi vengono trattati, anche se i due bordi hanno classi diverse.
Come si implementa una corretta classificazione dei bordi per un BFS su un grafico diretto?
EDIT
Ecco un'implementazione derivato da @redtuna risposta. Ho appena aggiunto un controllo per non recuperare il genitore della radice. devo JUnits prove che dimostrano funziona per grafi orientati e non orientati, nel caso di un ciclo, una linea retta, una forchetta, un esempio standard, un singolo bordo, ecc ....
@Override
public EdgeClass edgeClass(final V from, final V to)
{
if (!discovered.contains(to)) { return EdgeClass.TREE; }
int toDepth = depths.get(to);
int fromDepth = depths.get(from);
V b = to;
while (toDepth > 0 && fromDepth < toDepth)
{
b = parents.get(b);
toDepth = depths.get(b);
}
V a = from;
while (fromDepth > 0 && toDepth < fromDepth)
{
a = parents.get(a);
fromDepth = depths.get(a);
}
if (a.equals(b))
{
return EdgeClass.BACK;
}
else
{
return EdgeClass.CROSS;
}
}
Ho implementato e testato con successo questa soluzione. Funziona indipendentemente dal diretto/non orientato del grafico. Ho apportato alcune modifiche minori che posterò sotto la domanda. Grazie! –