【发布时间】:2015-04-14 15:20:13
【问题描述】:
在有向图上进行广度优先搜索时,我很难找到正确分类边的方法。
在广度优先或深度优先搜索期间,您可以将遇到的边缘分为 4 类:
- 树
- 返回
- 交叉
- 前进
Skiena [1] 给出了一个实现。如果你沿着一条边从 v1 移动到 v2,这里有一种在 java 中的 DFS 期间返回类的方法,以供参考。父映射返回当前搜索的父顶点,以及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;
我的问题是,对于有向图上的广度优先搜索,我无法正确使用它。例如:
下图 - 这是一个循环 - 没问题:
A -> B
A -> C
B -> C
从 A 开始 BFS 会发现 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;
}
}
【问题讨论】:
标签: algorithm graph-theory graph-algorithm breadth-first-search directed-graph