【问题标题】:Checking every bit is on some cycle检查每一位都在某个周期
【发布时间】:2015-12-31 02:59:29
【问题描述】:

我正在编写一个模型,其中:

节点表示为长度为 10 的位向量,每个位向量代表一些分子,边可以将源中存在的任何分子带到目标节点。

例如

S_Node : 0b0100000011 // 分子 0 , 1 , 8 出现在节点上

One_Edge : 0b0000000010 // 分子 1 在边缘流出

我必须强制边缘上的每个传出分子在某个周期返回源节点。分子必须在一个循环中返回意味着在循环的路径中,它必须存在于每个节点和它所采用的每个边缘上。 * 允许平行边。

分子 1 采用路径 S_Node -> Node_1 -> Node_2 ... -> S_Node。因此,分子 1 从边缘上的 S_Node 开始并穿过 Node_1 ...并在一个循环中回到 S_Node。因此,该分子满足条件。 同样,我必须检查每个边缘上的每个分子。

我正在以一种简单的可能方式检查每个节点有哪些可能的边缘出去,然后对于每个边缘有哪些可能存在的位,并强制每个节点在某个周期返回。

for  (i = 0; i < N; i++) {       // for each Node 
  for (j = 0; j < E; j++) {      // for each Edge going out frm node i
  // Lets say we have some way of finding E  
      if(edgeWeight & (1 << j)) {    //All outgoing bits
           // Enforcing that each will come  back 
           // On some Cycle

很容易看出我必须遍历所有节点,然后所有边缘都出去,然后对于这些边缘上的每个位,必须编写代码来执行相同的操作。执行本身必须至少迭代 no.Of Nodes #N。

有没有更好的方法来有效地做到这一点?在图论中检查相同事物的任何其他方法?谢谢

【问题讨论】:

  • 描述很不清楚,如果你问我...
  • 会努力改进的。
  • 如果我理解您必须强制执行每个“位”(分子)将循环 S_Node -&gt; Node_1 -&gt; Node_2 ... -&gt; S_Node 的循环,那么您似乎可以使用 单循环检查/强制执行并通过S_Node &amp; Node_1 &amp; Node_2 ... 检查每个位,当&amp; 的结果为1 时验证循环。
  • 那是有点不清楚的地方。从最初来看,您似乎担心每个节点上特定“位位置”的循环(您的示例位 1)。如果它像检查每个位位置的循环一样简单,那么在单个循环中每个位位置的每个连接节点的 anding 将起作用。您如何首先确定“循环从哪个节点开始?”。和“你如何确定每个连接的唯一性?”(例如S_Node(bit-1) 和X_Node(bit-1) 都连接到同一个分子上?
  • 这个问题不是很本地化吗?

标签: c algorithm graph-theory


【解决方案1】:

您似乎每个分子(每比特)都有一个有向图,只需按照您的技巧检查每个分子的任何非循环。

您可以采用 btillys 的方式检查周期,另一种选择是查看 strongly connected components。您本质上希望每个子图(对于给定的分子)是一个图,其中每个 connected component 实际上是强连接的。之前链接到的维基百科文章中提到了一些用于强连接组件的良好算法。

【讨论】:

  • 至极,砰!这是每个分子可用的另一种方法,您可以检查它所采用的轨迹,然后确保它是 scc 或者只是检查是否违反了进入的总分子与出去的不同。由于我还没有找到任何可扩展的方式来简单地做到这一点,所以我会这样做。问题是声明它,即声明它而不是检查它。因为如果我需要的只是检查,那么我可以在线性时间 tarzen 算法中完成。谢谢。
【解决方案2】:

节点的表示与问题无关。你有一个有向图。您希望验证对于每个节点和边,都存在一个包含该边的循环。并且您希望对此具有合理的效率(而不是对所有边缘的所有可能循环进行蛮力搜索)。

这是一个观察。假设您在图表G 中找到一个循环。考虑图表G',它与您的原始图表相同,除了循环已折叠为单个节点。您对G 的问题的答案与您对G' 的问题的答案相同,因为G 中的任何循环都会导致G' 中的循环(可能是一个自相交的循环,可以变成2循环),G' 中的任何循环都会导致G 中的循环(如果您点击折叠的节点,则跟随其循环直到找到退出点继续)。

因此,现在问题从循环的强力发现到崩溃循环,直到您有一个可以轻松回答问题的小图。因此,对于每个节点,对于每条边,您都会开始一条路径。你的路径一直持续到你发现了一个循环。任意循环。 (不一定要回到原来的节点!)折叠那个循环,并继续旅行,直到你不得不回溯(在这种情况下你的条件不满足)或者你设法循环回到你的原始节点,折叠那个循环,然后移动到另一个边缘。

如果你实现了这个,你会得到一个多项式算法,但不是你能做到的最好的。问题是创建循环折叠的新图是一项昂贵的操作。但是有一个技巧可以帮助。不要在每次找到循环时都折叠图表,而要尽量偷懒。为该循环创建一个新的“假节点”,并将该循环中的每个节点标记为前往该假节点。每次您看到一条通往节点的边时,通过这些映射执行递归搜索到您找到的最折叠的节点,并将您在该搜索中看到的所有内容标记为直接映射到那里。

如果你很好地实现了惰性位,你的整体算法应该以O(E) 结束,其中E 是图中的边数。考虑到无论你做什么,你都必须访问每一个边缘,所以实际上没有比这更好的了。

【讨论】:

  • 我认为折叠不适用于原始问题。如果我得到正确的 OP,他实际上拥有的是一个多路有向图,即他的位向量中的每个位都有一个图。当然,每个人都可以按照您的建议去做。
  • 仔细阅读,您显然是对的。也就是说,我相信按照我对每个位的建议去做将是正确的方法。
猜你喜欢
  • 1970-01-01
  • 2020-12-10
  • 1970-01-01
  • 2010-11-16
  • 1970-01-01
  • 2019-03-31
  • 2014-06-13
  • 2012-12-12
  • 1970-01-01
相关资源
最近更新 更多