我正在学习考试,无法解决这个问题:
我们给出了一个n <= 300 000个节点的图形,但是是压缩形式。该形式由m <= 300 000行组成,每行由三个数字给出:a_i,b_i,c_i,这意味着存在从节点a_i到区间[b_i,c_i]的所有节点的有向边。问题是确定给定图中是否存在循环,或者否。
例如输入:(数字n,m,然后是描述图形的m行)
4 5
1 2 3
1 4 4
2 3 4
3 4 4
4 1 1
答案是肯定的(例如周期:1-> 2-> 3-> 4-> 1)
并为此输入:
4 4
1 2 3
1 4 4
2 3 4
3 4 4
答案是否定的。
所以主要的问题是这个图表真的很大,我无法负担创建它并运行DFS。它必须更快地完成。我的第一个想法是使用拓扑排序算法。如果它工作,那么给定的图形中没有循环,否则存在循环。但是更新节点的程度是困难的(为了在该算法的每个步骤中选择具有deg_in = 0的节点)。我想也许使用区间树会有所帮助 - 当我删除节点v时,我可以看到他的邻接列表(此列表的元素将被给定间隔),并且对于所有间隔减少这些点的deg_in。所以我可以在对数时间检查节点度是多少,但我仍然无法快速更新deg_in = 0的节点列表。我不知道,也许我正在尝试一种无法修复的解决方案?
有人可以帮忙吗?
答案 0 :(得分:0)
我将尝试为该算法制作元代码。这将是图形行进算法的特例。专业是关于线路的包装存储。
// Outer loop to check all nodes
CheckedNodes = (empty)
for n1 in 1 .. n {
if (not(CheckedNodes contains n1)) {
add n1 to CheckedNodes
VisitedNodes = (empty) // initialization
VisitableNodes = { n1 } // start the walk from here
// Inner loop to walk through VisitableNodes
While (VisitableNodes is not empty) {
n2 := select one from VisitableNodes
remove n2 from VisitableNodes
add n2 to CheckedNodes // this will stop processing again
for all lines starting from n2 { // we add all points for all lines
for n3 in line.start .. line.end {
if (VisitedNodes contains n3) {
// we found an already visited node
return "Circle found in Graph!"
} else {
// otherwise we should visit that later
add n3 to VisitableNodes
}
}
}
}
}
}
// we have not found a circle
return "No circle found in Graph!"
问题是实施。在CheckedNodes
和VisitedNodes
的算法中,我使用集合,它们 - 带有整数索引 - 可以通过布尔数组(或类似的东西)轻松实现。 VisitableNodes
是一个列表,它应该由类似列表的结构实现。