Мне трудно найти способ правильно классифицировать ребра при первом поиске по ориентированному графу.
Во время поиска по ширине или глубине вы можете классифицировать ребра, встреченные с 4 классами:
- ДЕРЕВО
- НАЗАД
- Перекрестная
- ВПЕРЕД
Skiena [1] дает реализацию. Если вы перемещаетесь по краю от v1 до v2, вот способ вернуть класс во время DFS в java, для справки. Карта родителей возвращает родительскую вершину для текущего поиска и метод timeOf()
, время, в которое была обнаружена вершина.
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;
Моя проблема заключается в том, что я не могу получить это правильно для первого поиска Breadth на ориентированном графе. Например:
Следующий график - это цикл - это нормально:
A -> B
A -> C
B -> C
BFSing из A, B будет обнаружен, затем C. Ребра eAB и eAC являются краями TREE, а когда eBC пересекается последним, B и C обрабатываются и обнаруживаются, и это ребро должным образом классифицируется как CROSS.
Но простой цикл не работает:
A -> B
B -> C
C -> A
Когда край eCA пересекается последним, A обрабатывается и обнаруживается. Таким образом, этот край неправильно помечен как CROSS, должен ли он быть краем BACK.
В действительности нет разницы в том, как обрабатываются два случая, даже если оба ребра имеют разные классы.
Как вы реализуете правильную классификацию полей для BFS на ориентированном графе?
ИЗМЕНИТЬ
Здесь реализована реализация, полученная из ответа @redtuna. Я просто добавил проверку не для получения родительского корня. У меня есть тесты JUnits, которые показывают, что он работает для направленных и неориентированных графов, в случае цикла, прямой линии, вилки, стандартного примера, одного края и т.д.
@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;
}
}