【问题标题】:Algorithm for creating dedicated paths between two nodes在两个节点之间创建专用路径的算法
【发布时间】:2013-08-27 23:19:14
【问题描述】:

我有一些文本的顺序遵循特定的顺序。一些文本会因遍历的轨迹而改变。我的目标是为每个页面生成静态页面,并通过链接将它们相互连接。

问题是解决一个为印刷书籍生成文本的工具的问题(显然是静态的)。因此,假设您正在阅读示例 1 中表示的一本书(如下图所示)。最初,您在节点 A 中,此页面的文本是“转到页面 B 或页面 C”。选择节点 C,然后选择 F -> B -> E -> H,您将在节点 H 中看到一个内容,该内容应该与您是否被 A -> B -> D 遍历时看到的内容不同-> H,例如。由于是印刷书,所以需要复制一些路径,以便根据遍历的路径改变一些节点的内容。

例子:

在这个例子中,我有两种遍历的可能:

A -> B -> D
A -> C -> D

预期结果:

Page 1: A (link to page 2 and 3)
Page 2: B (link to page 4)
Page 3: C (link to page 5)
Page 4: D
Page 5: DD'

这个简单的例子生成了 5 个页面,一旦第 4 页有一部分文本应该只在阅读通过第 3 页时才显示。

为了模拟这个问题,我选择使用图论。为了更好地理解,我在下图中绘制了我要解决的问题的两个示例:

请注意,红色虚线边缘实际上不是边缘。这些是我用来表示给定节点 X 的内容何时因访问节点 Y 而发生变化的方式(读作“如果到达 X 的路径经过 Y,则节点 X 的内容发生变化”)。

我阅读了很多关于图、遍历策略(BFS 和 DFS)和其他一些主题的文章。我的目标是开发一种算法,以一种可能生成前面提到的页面的方式重新排列给定的图形。我没有发现任何众所周知的问题可以解决这个问题,但我相信它应该已经存在。我的研究没有发现任何有用的东西,所以我尝试自己解决。

我成功的方法是向上遍历图表以找到一个节点,该节点包含依赖于其他节点的内容。找到此节点后,查找从依赖节点到当前节点的所有路径。遍历这些路径,复制包含多个传入边的所有节点,删除先前的连接并将当前节点与复制的节点连接,依此类推,直到消耗路径的所有节点。这种算法效果很好,但这种方法效率不高,而且对于长文本可能会很慢。

我的问题是:您知道解决此问题的其他更好方法吗?有没有什么理论或已知的算法可以解决这类问题?

提前致谢。

【问题讨论】:

  • 例1中从A到I经过H的路径有5条,为什么只有H1~H4?是不是路径 ABDHI 和 ACGHI 在节点 H 上支持相同的内容?
  • 是的,因为 H 的内容只会随着 E 和 F 的变化而改变,所以我们有以下可能的组合: - 不通过 E 或 F (A->B->D->H) -通过 E (A->B-E->H> - 通过 F (A->C->F->B->D->H) - 通过 E 和 F (A->C->F-> B->E->H>

标签: algorithm math graph tree graph-algorithm


【解决方案1】:

做一个 DFS,当你看到一个访问过的节点时,复制它,断开你刚刚访问过的链接并将新节点标记为已访问,然后从这个节点继续 dfs。此方法不会多次访问节点,因此是最快的(意味着它只会访问 H1 2 次而不是 n 或 k 次)。

这在输出图方面是线性的。也就是说,如果输出图有 V' 个顶点和 E' 个边,它的顺序是 O(V'+E')。您无法取得更好的成绩,因为您必须至少访问输出图中的所有内容一次。

【讨论】:

  • 只要确保 DFS 及其实现对您来说非常清楚,这将是显而易见的答案
  • 但是我不需要在所有情况下都复制,只是当我有一个节点由于经过特定节点而其内容发生变化时(注意红色边缘,表示“访问依赖”)。一旦降低成本,我的目标是尽可能少地复制页面。
  • 例如:我在 H 节点中有一个文本片段,如果节点 E 和/或 F 被访问,我应该显示它。为了实现这一点,我需要在 E -> H 和 F -> H 之间创建一条专用路径。因此,例如,当我访问 E 节点时,我将开始遍历一条向我显示与我不同的内容的路径例如,看看我是否通过了 D 节点。
  • 好吧,您可以通过创建自定义边来实现这一点,如果节点已经“访问过”或“未访问过”并且 DFS 未遍历该节点,您可以使用这些边访问这些边。你不需要这样做。
  • 不,我想你没有理解我的问题,可能是我不够清楚。问题是解决印刷材料的问题(显然是静态的)。所以假设你正在阅读示例 1 中表示的一本书。你在节点 A 中,该页面的文本是“转到页面 B 或页面 C”,然后选择 C,然后选择 F-> B->E->H。例如,您在 H 中看到的内容应该不同于通过 A -> B -> D -> H 遍历的内容。因为它是一本书,所以我需要复制一些路径,以便根据遍历的路径更改一些节点的内容。
【解决方案2】:

我假设这些红色边缘的规则是策略性的。将多个内容保留在一个节点中,而不是复制它。现在,由于显示的内容取决于到达它所采用的路径,因此在每一步我们都可以检查 DFS 的“堆栈”以查看到达它所采用的路径。堆栈将为我们提供到达它所采用的确切路径(但请注意,它不会详细说明路径是否访问了父母的其他后代)。然后我们比较我们已有的静态规则并显示内容。

时间复杂度分析(最坏情况): 在 DFS 的每一步,我们都会根据规则检查整个堆栈。堆栈的最大长度可以是 h(其中 h 是树的高度)。因此时间复杂度为 O((V+E)*h)。

或者,如果 path 访问过父事项的其他后代(例如分析路径 A->B->E 并且如果它很重要 D 已经访问过),您可以根据规则。再次在一个节点中保留多个内容。在决定显示哪些内容时,只需检查“源自该顶点的红色边”的“端点”是否已被访问。现在使用规则来显示相应的内容

【讨论】:

  • 我无法在运行时“检查堆栈”,因为它将在书页中(再次,我需要生成重复页面以到达正确的页面,其中包含先前评估和呈现的正确内容由发电机)。如果我在生成页面时这样做,它将最终陷入无限循环。为了避免无限循环,我可以引入一堆访问过的节点,但它仍然不起作用,因为已经访问过的路径(循环)不会再次渲染。
猜你喜欢
  • 2012-05-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多