Ich habe Schwierigkeiten, einen Weg zu finden, um die Kanten richtig zu klassifizieren, während eine Breitensuche in einem gerichteten Graphen durchgeführt wird.Kantenklassifikation während der Breite-zuerst-Suche auf einem gerichteten Graph
- TREE
- BACK
- CROSS
FORWARD:
Während einer Breiten ersten oder Tiefensuche, können Sie die Ränder mit 4 Klassen erfüllt klassifizieren Skiena [1] gibt eine Implementierung. Wenn Sie sich entlang einer Kante von v1 nach v2 bewegen, können Sie die Klasse während eines DFS in Java als Referenz zurückgeben. Die Eltern-Map gibt den übergeordneten Vertex für die aktuelle Suche und die timeOf()
-Methode den Zeitpunkt zurück, zu dem der Vertex erkannt wurde.
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;
Mein Problem ist, dass ich es nicht richtig für einen Breitensuche auf einem gerichteten Graphen erhalten können. Zum Beispiel:
Das folgende Diagramm - dass eine Schleife - ist ok:
A -> B
A -> C
B -> C
BFSing von A, B wird festgestellt werden, dann C. Die Kanten EAB und eAC sind TREE Kanten und wenn eBC wird zuletzt überquert, B und C werden verarbeitet und entdeckt, und diese Kante wird korrekt als CROSS klassifiziert.
Aber eine einfache Schleife funktioniert nicht:
A -> B
B -> C
C -> A
Wenn der Rand eCA letzten gekreuzt wird, wird verarbeitet und A entdeckt. Diese Kante wird also fälschlicherweise als CROSS bezeichnet, unabhängig davon, ob es sich um eine BACK-Kante handelt.
Es gibt tatsächlich keinen Unterschied in der Art, wie die beiden Fälle behandelt werden, selbst wenn die beiden Kanten unterschiedliche Klassen haben.
Wie implementieren Sie eine geeignete Kantenklassifizierung für ein BFS auf einem gerichteten Graphen?
EDIT
Hier eine Implementierung von @redtuna Antwort abgeleitet. Ich habe gerade einen Check hinzugefügt, um den Eltern des Stammes nicht zu holen. Ich habe JUnits Tests, die es für gerichtete und ungerichtete Graphen, in dem Fall einer Schleife zeigen arbeitet, wird eine gerade Linie, eine Gabel, ein Standard beispielsweise eine einzige Kante, etc ....
@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;
}
}
Ich habe diese Lösung erfolgreich implementiert und getestet. Es funktioniert unabhängig von der gerichteten/ungerichteten Ausrichtung des Graphen. Ich habe ein paar kleine Änderungen vorgenommen, die ich unter der Frage veröffentlichen werde. Vielen Dank! –