简体   繁体   English

树的最小权重顶点覆盖

[英]minimum weight vertex cover of a tree

There's an existing question dealing with trees where the weight of a vertex is its degree, but I'm interested in the case where the vertices can have arbitrary weights.存在一个处理树的现有问题,其中顶点的权重是它的度数,但我对顶点可以具有任意权重的情况感兴趣。

This isn't homework but it is one of the questions in the algorithm design manual, which I'm currently reading;这不是作业,但它在算法设计手册,这我目前正在读的问题之一; an answer set gives the solution as一个答案集给出了解决方案

  1. Perform a DFS, at each step update Score[v][include], where v is a vertex and include is either true or false;执行一次DFS,在每一步更新Score[v][include],其中v是一个顶点,include要么是true要么是false;
  2. If v is a leaf, set Score[v][false] = 0, Score[v][true] = w v , where w v is the weight of vertex v.如果 v 是叶子,则设置 Score[v][false] = 0, Score[v][true] = w v ,其中 w v是顶点 v 的权重。
  3. During DFS, when moving up from the last child of the node v, update Score[v][include]: Score[v][false] = Sum for c in children(v) of Score[c][true] and Score[v][true] = w v + Sum for c in children(v) of min(Score[c][true]; Score[c][false])在 DFS 期间,当从节点 v 的最后一个子节点向上移动时,更新 Score[v][include]:Score[v][false] = Sum for c in children(v) of Score[c][true] 和 Score [v][true] = w v + sum for c in children(v) of min(Score[c][true]; Score[c][false])
  4. Extract actual cover by backtracking Score.通过回溯 Score 提取实际覆盖。

However, I can't actually translate that into something that works .但是,我实际上无法将其转化为有效的内容 (In response to the comment: what I've tried so far is drawing some smallish graphs with weights and running through the algorithm on paper, up until step four, where the "extract actual cover" part is not transparent.) (作为对评论的回应:到目前为止,我所尝试的是绘制一些带有权重的小图形并在纸上运行算法,直到第四步,其中“提取实际封面”部分不透明。)

In response Ali's answer: So suppose I have this graph, with the vertices given by A etc. and the weights in parens after:作为回应阿里的回答:所以假设我有这个图,顶点由A等给出,权重在后面:

A(9)---B(3)---C(2) \\ \\ E(1) D(4)

The right answer is clearly {B,E} .正确答案显然是{B,E}

Going through this algorithm, we'd set values like so:通过这个算法,我们会像这样设置值:

  • score[D][false] = 0 ; score[D][false] = 0 ; score[D][true] = 4
  • score[C][false] = 0 ; score[C][false] = 0 ; score[C][true] = 2
  • score[B][false] = 6 ; score[B][false] = 6 ; score[B][true] = 3
  • score[E][false] = 0 ; score[E][false] = 0 ; score[E][true] = 1
  • score[A][false] = 4 ; score[A][false] = 4 ; score[A][true] = 12

Ok, so, my question is basically, now what?好的,所以,我的问题基本上是,现在呢? Doing the simple thing and iterating through the score vector and deciding what's cheapest locally doesn't work;做简单的事情并遍历score向量并决定本地最便宜的东西是行不通的; you only end up including B .你最终只会包括B Deciding based on the parent and alternating also doesn't work: consider the case where the weight of E is 1000 ;基于父和交替的决定也不起作用:考虑E的权重为1000 now the correct answer is {A,B} , and they're adjacent.现在正确答案是{A,B} ,它们是相邻的。 Perhaps it is not supposed to be confusing, but frankly, I'm confused.也许它不应该令人困惑,但坦率地说,我很困惑。

There's no actual backtracking done (or needed).没有完成(或需要)实际的回溯。 The solution uses dynamic programming to avoid backtracking, since that'd take exponential time.该解决方案使用动态编程来避免回溯,因为这需要指数级的时间。 My guess is "backtracking Score" means the Score contains the partial results you would get by doing backtracking.我的猜测是“回溯分数”意味着分数包含您通过回溯获得的部分结果。

The cover vertex of a tree allows to include alternated and adjacent vertices.树的覆盖顶点允许包括交替和相邻的顶点。 It does not allow to exclude two adjacent vertices, because it must contain all of the edges.它不允许排除两个相邻的顶点,因为它必须包含所有边。

The answer is given in the way the Score is recursively calculated.答案是通过递归计算 Score 的方式给出的。 The cost of not including a vertex, is the cost of including its children.不包括顶点的成本是包括其子节点的成本。 However, the cost of including a vertex is whatever is less costly, the cost of including its children or not including them, because both things are allowed.然而,包括顶点的成本是较低的成本,包括其子节点的成本或不包括它们的成本,因为两者都是允许的。

As your solution suggests, it can be done with DFS in post-order, in a single pass.正如您的解决方案所建议的那样,它可以通过 DFS 一次性完成。 The trick is to include a vertex if the Score says it must be included, and include its children if it must be excluded, otherwise we'd be excluding two adjacent vertices.诀窍是如果 Score 说必须包含一个顶点,则包含它的子节点,如果必须排除它,则包含它的子节点,否则我们将排除两个相邻的顶点。

Here's some pseudocode:这是一些伪代码:

find_cover_vertex_of_minimum_weight(v)
  find_cover_vertex_of_minimum_weight(left children of v)
  find_cover_vertex_of_minimum_weight(right children of v)
  Score[v][false] = Sum for c in children(v) of Score[c][true]
  Score[v][true] = v weight + Sum for c in children(v) of min(Score[c][true]; Score[c][false])
  if Score[v][true] < Score[v][false] then
    add v to cover vertex tree
  else
    for c in children(v)
      add c to cover vertex tree

It actually didnt mean any thing confusing and it is just Dynamic Programming , you seems to almost understand all the algorithm.它实际上并不意味着任何令人困惑的事情,它只是动态编程,您似乎几乎了解所有算法。 If I want to make it any more clear, I have to say:如果我想说得更清楚,我必须说:

  1. first preform DFS on you graph and find leafs.首先在你的图表上预制 DFS 并找到叶子。
  2. for every leaf assign values as the algorithm says.正如算法所说,为每个叶子分配值。
  3. now start from leafs and assign values to each leaf parent by that formula.现在从叶子开始,并通过该公式为每个叶子父代赋值。
  4. start assigning values to parent of nodes that already have values until you reach the root of your graph.开始为已经有值的节点的父节点赋值,直到到达图的根。

That is just it, by backtracking in your algorithm it means that you assign value to each node that its child already have values.就是这样,通过在您的算法中回溯,这意味着您将值分配给其子节点已经具有值的每个节点。 As I said above this kind of solving problem is called dynamic programming.正如我上面所说,这种解决问题的方法称为动态规划。

Edit just for explaining your changes in the question.编辑只是为了解释你在问题中的变化。 As you you have the following graph and answer is clearly B,E but you though this algorithm just give you B and you are incorrect this algorithm give you B and E.由于您有下图,答案显然是 B、E,但您虽然此算法只给您 B,但您不正确,此算法给您 B 和 E。

A(9)---B(3)---C(2) \\ \\ E(1) D(4)

score[D][false] = 0; score[D][true] = 4
score[C][false] = 0; score[C][true] = 2
score[B][false] = 6 this means we use C and D; score[B][true] = 3 this means we use B
score[E][false] = 0; score[E][true] = 1
score[A][false] = 4 This means we use B and E; score[A][true] = 12 this means we use B and A.

and you select 4 so you must use B and E. if it was just B your answer would be 3. but as you find it correctly your answer is 4 = 3 + 1 = B + E.并且您选择了 4,因此您必须使用 B 和 E。如果只是 B,您的答案将是 3。但是,如果您正确找到,您的答案是 4 = 3 + 1 = B + E。

Also when E = 1000同样当 E = 1000

A(9)---B(3)---C(2) \\ \\ E(1000) D(4)

it is 100% correct that the answer is B and A because it is wrong to use E just because you dont want to select adjacent nodes.答案是 B 和 A 是 100% 正确的,因为仅仅因为您不想选择相邻节点而使用 E 是错误的。 with this algorithm you will find the answer is A and B and just by checking you can find it too.使用此算法,您会发现答案是 A 和 B,只需检查您也可以找到它。 suppose this covers :假设这包括:

C D A = 15
C D E = 1006
A B = 12

Although the first two answer have no adjacent nodes but they are bigger than last answer that have adjacent nodes.虽然前两个答案没有相邻节点,但它们比具有相邻节点的最后一个答案大。 so it is best to use A and B for cover.所以最好用A和B做掩护。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM