木の最小頂点カバーを取得するための適切なアルゴリズムは何ですか?
入力:
ノードのネイバー。
出力:
頂点の最小数。
ここの回答を読んでもよくわからなかったので、ここから投稿しようと思いました
一般的な考え方は、任意のノードでツリーをルートし、そのルートがカバー内にあるかどうかを確認することです。そうである場合は、再帰によって、その子をルートとするサブツリーの最小頂点カバーを計算します。そうでない場合は、ルートとその子の間のすべてのエッジがカバーされるように、ルートのすべての子が頂点カバー内にある必要があります。この場合、ルートの孫に対して再帰します。
たとえば、次のツリーがあるとします。
A
/ \
B C
/ \ / \
D E F G
調べると、最小頂点カバーが であることがわかります{B, C}
。この最小カバーを見つけます。
ここでは から始めA
ます。
と の 2 つのサブツリーに移動し、B
このC
アルゴリズムを再帰します。カバーされていたとしても、カバーに含まれる必要があるかどうかについては何も言えB
ません。C
AB
AC
B
C
(ルートとその子の 1 つが最小カバー ( ) にある次のツリーについて考えてください{A, D}
)
A
/|\___
B C D
/|\
E F G
)
AB
しかし、 andをカバーする必要があることはわかっているので、カバーにandAC
を追加する必要があります。andはカバーに含まれているため、 andを再帰する代わりに、その子を再帰できます(実行したとしても、それ以上の情報は得られません)。B
C
B
C
B
C
をルートとする最小C(x)
カバーのサイズとしx
ます。
それで、
C(x) = min (
1 + sum ( C(i) for i in x's children ), // root in cover
len(x's children) + sum( C(i) for i in x's grandchildren) // root not in cover
)
T(V,E) はツリーです。これは、任意の葉について、最小頂点被覆には葉または葉に隣接する頂点のいずれかを含める必要があることを意味します。これにより、頂点カバー S を見つけるための次のアルゴリズムが得られます。
あとは、元の木に頂点が 1 つしかない場合は 1 を返し、再帰を開始せず、最小の頂点カバーを計算できることを確認するだけです。
編集:
実際、少し考えてみれば、単純な DFS バリアントで実現できます。
ここで、あなたの質問に対するより関連性の高い回答を見つけていただければ幸いです。
私は自分のソリューションについて考えていましたが、おそらくそれを磨く必要がありますが、動的プログラミングがタグの1つにある限り、おそらく次のことが必要です:
これを読んだ後。ウィキの記事に記載されているため、最大の独立したセットを見つけるために上記のアルゴリズムを変更しました
セットは、その補数が頂点カバーである場合にのみ独立しています。
したがって、最小値を最大値に変更することで最大の独立集合を見つけ、最小の頂点カバーを補うことができます。これは、両方の問題が同等であるためです。
{- Haskell implementation of Artem's algorithm -}
data Tree = Branch [Tree]
deriving Show
{- first int is the min cover; second int is the min cover that includes the root -}
minVC :: Tree -> (Int, Int)
minVC (Branch subtrees) = let
costs = map minVC subtrees
minWithRoot = 1 + sum (map fst costs) in
(min minWithRoot (sum (map snd costs)), minWithRoot)
DFS ベースのアルゴリズムを使用して、この問題を解決できます。
DFS(node x)
{
discovered[x] = true;
/* Scan the Adjacency list for the node x*/
while((y = getNextAdj() != NULL)
{
if(discovered[y] == false)
{
DFS(y);
/* y is the child of node x*/
/* If child is not selected as a vertex for minimum selected cover
then select the parent */
if(y->isSelected == false)
{
x->isSelected = true;
}
}
}
}
リーフ ノードが頂点カバーに選択されることはありません。
単純に線形プログラムを使用して、最小頂点被覆問題を解決します。整数線形プログラムとしての定式化は、次のようになります: ILP の定式化
あなた自身の実装がこれらの高度に最適化された LP ソルバーよりも高速になるとは思いません。