【问题标题】:Subset of vertices顶点子集
【发布时间】:2012-12-03 17:12:35
【问题描述】:

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

这就是问题所在: “给你一个连通的无向图,它有 N 个顶点和 N 个边。每个顶点都有一个成本。你必须找到一个顶点子集,以便子集中顶点的总成本最小,并且每条边都与子集中的至少一个顶点。”

提前谢谢你!

P.S:我长期以来一直在寻找解决方案,我提出的唯一想法是回溯或二分图中的最小成本匹配,但是对于 N=100000,这两个想法都太慢了。

【问题讨论】:

  • 首先尝试自己制定解决方案。
  • "N 顶点和 N 边" - 对吗?相同数量的顶点和边?这意味着该图是一棵具有一条“额外”边的树。
  • 是的“N个顶点和N个边”是正确的。
  • 哦,是的。请注意,一般情况下的问题(不限于 N 条边)是vertex cover problem,这是一个经典的 NP-Complete 问题。然而,我的直觉告诉我,对于更简单的问题,情况并非如此。

标签: c++ algorithm


【解决方案1】:

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

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

然后删除此循环中的任何边缘。与这条边相关的两个顶点是 uv。在这个边缘去除之后,我们有一棵树。将其解释为具有根 u 的根树。

这棵树的动态编程循环可以这样定义:

  • w0[k] = 0(对于叶节点)
  • w1[k] = vertex_cost(对于叶节点)
  • w0[k] = w1[k+1](对于有一个后代的节点)李>
  • w1[k] = vertex_cost + min(w0[k+1], w 1[k+1])(对于有一个后代的节点)
  • w0[k] = sum(w1[k+1], x1[k+1], ...)(用于分支节点)
  • w1[k] = vertex_cost + sum(min(w0[k+1], w1[k+1]), min(x0[k+1], x1[k+1]), ...)

这里k是节点深度(到根的距离),w0是从节点w开始的子树的成本> 当 w 不在“子集”中时,w1 是从节点 w 开始的子树的成本strong> 当 w 在“子集”中时。

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

“子集”的最优成本确定为 min(u0,1, u1,0强>、u1,1)。要获取“子集”本身,请将反向指针与每个子树成本一起存储,并使用它们来重建子集。

【讨论】:

    【解决方案2】:

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

    1. N 顶点和 (N-1) 边图是一棵树。您的图有 N 个顶点和 N 个边。首先找到导致循环的可怕边缘并将图制作成树。您可以使用 DFS 来查找循环 (O(N))。删除循环中的任何一条边都会生成一棵可能的树。在极端情况下,您会得到 N 棵可能的树(原始图是一个圆圈)。

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

    【讨论】:

    • 不能多条边作为驱逐的候选者吗?我在这里考虑一个“圆圈”作为一个极端的例子。在这种情况下,您需要将 DPA 应用于每个可能的树...
    • @MatthieuM。哦,是的,选择要移除的边缘确实很重要。我修改了我的答案。谢谢!
    猜你喜欢
    • 1970-01-01
    • 2016-06-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多