顶点子集

时间:2012-12-16 09:35:25

标签: c++ algorithm

我有一个家庭作业问题,我不知道如何解决它。如果你能给我一个想法,我将非常感激。

这是问题所在: “你得到一个连通的无向图,它有N个顶点和N个边。每个顶点都有一个成本。你必须找到一个顶点的子集,这样子集中顶点的总成本是最小的,并且每个边都是偶然的来自子集的至少一个顶点。“

提前谢谢!

P.S:我已经考虑了很长一段时间的解决方案,我想出的唯一想法是回溯或二分图中的最低成本匹配,但这两个想法对于N = 100000而言都太慢了。

2 个答案:

答案 0 :(得分:2)

这可以使用动态编程在线性时间内解决。

具有N个顶点和N个边的连通图仅包含一个周期。从检测此循环开始(借助深度优先搜索)。

然后移除此循环中的任何边缘。入射到此边缘的两个顶点是 u v 。删除此边缘后,我们有一棵树。将其解释为根 u 的根树。

此树的动态编程重现可以这样定义:

  • w 0 [k] = 0(对于叶节点)
  • w 1 [k] = vertex_cost(对于叶节点)
  • w 0 [k] = w 1 [k + 1](对于有一个后代的节点)
  • w 1 [k] = vertex_cost + min( w 0 [k + 1],< strong> w 1 [k + 1])(对于有一个后代的节点)
  • w 0 [k] = sum( w 1 [k + 1], x 1 [k + 1],...)(对于分支节点)
  • w 1 [k] = vertex_cost + sum(min( w 0 [k + 1] , w 1 [k + 1]),min( x 0 [k + 1], x 1 [k + 1]),...)

此处k是节点深度(距离根的距离), w 0 是从节点 w <开始的子树的成本/ strong>当 w 不在“子集”中时, w 1 是从节点 w开始的子树的成本 w 在“子集”中时。

对于每个节点,只应计算两个值: w 0 w 1 。但对于循环中的节点,我们需要4个值: w i,j ,其中i = 0,如果节点 v 不在“subset”,如果节点 v 在“子集”中,则i = 1,如果当前节点不在“子集”中,则j = 0,如果当前节点在“子集”中,则j = 1

“子集”的最优成本确定为min( u 0,1 u 1,0 u 1,1 )。要获得“子集”本身,存储后向指针以及每个子树成本,并使用它们来重建子集。

答案 1 :(得分:1)

由于边数对于相同数量的顶点是严格的,因此它不是NP-Complete的常见Vertex cover problem。我认为这里有一个多项式解决方案:

  1. N个顶点和(N-1)个边图是树。您的图形有N个顶点和N个边。首先找到导致循环的可怕边缘并将图形设置为树。您可以使用DFS查找循环(​​O(N))。删除循环中的任何一个边将构成一个可能的树。在极端条件下,您将获得N个可能的树(原始图形为圆形)。

  2. 将简单的动态规划算法(O(N))应用于每个可能的树(O(N^2)),然后找到成本最低的算法。