最小スパニングツリー:
原画像のn個の頂点を持つスパニングツリーグラフを通信することは、最小限の接続部分グラフであり、元のグラフ内の全てのn個のノードを含み、図に保ちながら最小の通信があります。単にだけであるn個の点のn-1エッジがグラフに接続されています。
最小スパニングツリーがスパニングツリー最小重量短いため、それは、最小スパニングツリーの和のすべての右端です。
一般的に解決する最小全域木問題、次の2つの方法があります。
、プリムのアルゴリズム
参照ファインマンさんのブログ
一般的に、隣接行列ストレージ構造としてプリム法。
アルゴリズムのアイデア:頂点が、支配的である頂点に、それらに利用可能な現在の最小重量エッジを選択することにより、開始頂点から出発して、スパニングツリーに追加されました:
通信ネットワークから1 N = {Vは、E}は頂点Uで0スタート、エッジ(Uは、それに関連付けられた最小加重値を有する、選択0頂点がUにまたがる頂点の集合に追加され、V)を、インチ
2.他の頂点がUの各辺にないながら、各工程の後、U最小量側に頂点から選択され、(U、V)は、それが集合Uの頂点に追加されます ネットワークのすべての頂点は、スパニングツリーの頂点に追加されるまで、だから、これまでにUを設定し、継続します。
テンプレートのタイトルリンク:プリム最小スパニングツリーアルゴリズム
時間複雑さの簡易版O(n²)アルゴリズムのテンプレート:
#include <iostreamの> する#include <cstdioを> する#include <アルゴリズム> の#include <CStringの> 使用して 名前空間STD。 CONSTの INT N = 500 + 10 。 INTのN、M。 INT G [N] [N]、DIS [N]、VIS [N]。 ボイドプリム() { memsetの(DIS、0x1Fの、はsizeof DIS)。 DIS [ 1 ] = 0 ; 用(INT J = 1 ; J <= nであり、j ++ ) { int型 min_len = 2E + 9、K。 以下のために(int型 i = 1 ; iは= N <; iは++ ) { 場合(VIS [I] && DIS [I] <!min_len) { min_len = DIS [i]は、 kは = I。 } } VIS [K] = 1 。 以下のために(int型 i = 1 ; iが<= N; iは++ ) { 場合(VIS [I] && DIS [I]!> G [K] [i])と DIS [I] = G [K] [I]。 } } } int型メイン() { scanf関数(" %D%dの"、&N、&M)。 memsetの(G、0x1Fの、はsizeofのG)。 以下のために(int型 I = 1 ; I <= M; iは++ ) { int型、U、V、W; scanf関数(" %D%D%D "、&U&V、およびW) G [U] [V] = G [V] [U] =分(G [U] [V]、W)。 // 因为有重边、分取所以 } )プリム(。 int型 ANS = 0 ; 以下のために(int型 i = 1 ; iが<= N; iは++)ANS + = DIS [i]は、 もし(ANS> 1E7)のprintf(" 不可能\ nを" ); 他のprintf(" %d個の\ nを" 、ANS)。 リターン 0 ; }
ダイクストラと同様、プリムアルゴリズムはまた、代わりに優先度キュースタック、ヒープを最適化するために使用することができる、のプリムアルゴリズム最適化の時間複雑O(mlogn)テンプレート(フォワード星のため図ストレージ):
ボイド Prim_heap(INTの点) { memsetの(DIS、0x1Fの、はsizeof (DIS))。 PRIORITY_QUEUE <ペア< int型、int型 >> Q; DIS [ポイント] = 0 ; q.push(make_pair(0、1 ))。 一方、(!q.empty()) { int型 K = q.top()は、第2。 q.pop(); V [K] = 1 。 以下のために(int型 I =さh [k]を、私は=! - 1 ; I = エッジ[I] .next) { intは = [I] .TO、W =縁にエッジ[I] .W; IF(!V DIS && [する]> [する] W) { [に対する] DIS = Wを、 q.push(make_pair(、DIS ))に、[する]; // プライオリティキュー大ルートヒープが小さいルートヒープ小さなショー動作なる:ちょうど' - '記号; } } } のための(INT I = 1 ; I <= N; I ++の)IF(DIS [I] == 0x1f1f1f1f)=フラグにはfalse ; // か否かを判断ツリースパニング最小の存在 リターン; }
二、クラスカルのアルゴリズム
プリムのアルゴリズム、クラスカル更により一般的に比較し、その理由は、小さなコードテンプレートの量とSilu李クラスカル法の理解です。
アルゴリズムのアイデア:ネットワーク中、n頂点、エッジ及び設定サブピクチャが空であるが、各ツリーのルート図として各頂点のハンドルは、その後、右から選択するだけエッジEのセットを含む第1の構成物最小値側、同じストリップ側の2つの頂点が低下した場合、ツリーの部分の異なる側に属する2つの頂点は、それが、逆に、サブマップ、すなわち合成ツリー2つのツリー追加された場合ツリーは、望ましくないが、やはり重量の最小エッジを除去すべきです。そしてように、縁部までのn-1を含有するのみ森林木、すなわちサブグラフまで。
ステップ:
-
図新しいG、ノードGは、同じ画像を有するが、全くエッジが存在しません。
-
小から大への重量原すべての側面。
-
このエッジは、このエッジグラフGに付加し、なく、同じ連結成分にグラフG内の2つのノードを接続する場合、最小量の縁から出発。
-
G内のすべてのノードが同一の連結成分になるまで3が繰り返されます。
各選択された最小量側の先端を位置決めするために、単純で、双方が(実装を設定互いに素な操作をマージ)接続された通信は、通信場合、二つのマージか否かが判断されます。エンド・カウントがn-1に等しいレコードの合計数。
テンプレートのタイトルリンク:クラスカル最小スパニングツリーアルゴリズム
コードは以下の通りである:の時間計算量O(mlogm)
#include <iostreamの> する#include <アルゴリズム> の#include <cstdioを> する#include <CStringの> 使用して 名前空間STD。 CONSTの INT N = 100000 + 10、M = 200000 + 10 。 構造体のエッジ{ int型U、V、W。 ブール 演算子 <(constのエッジ&E)のconst { リターン <W Ewを。 } }エッジ[M]。 INT FA [N]。 INTのN、M、CNT、ANS。 int型を見つける(int型X) { 場合(FA [X] == x)をリターンX。 他 戻り FAは[X] = 見つける(FA [X])。 } int型のmain() { scanf関数(" %D%dの"、&N、&M)。 以下のために(int型 i = 1 ; iが<= N; iは++)FA [I] = I。 以下のために(int型私= 1 ; I <= M; iが++ ) { int型、B、C; scanf関数(" %D%D%D "、&、&B、&C)。 エッジ[I] .U = A、エッジ[I] .V = B;エッジ[I] .W = C。 } ソート(エッジ+ 1、エッジ+ M + 1 )。 用(int型 I = 1 ; I <= M Iは++ ) { int型、U =見つける(エッジ[I] .U)、V =見つける(エッジ[I] .V)、W = エッジ[I] .W。 もし(!U = V) { CNT ++ ; FA [U] = V。 ANS + = W。 } } もし(CNT == N- 1)のprintf(" %d個の\ n " 、ANS)。 他のprintf(" 不可能\ nを" ); 戻り 0 ; }
三、プリム、Prim_heap、クラスカルのアルゴリズムの時間計算量の比較
参照Gバイキングのブログ
結論:
クラスカルが劣化よりも、図中、好ましくは、図クラスカルよりも緻密で1.Prim、疎。
2.Prim_heap時間の複雑さのすべての回で十分ではなく、巨大なスペースの消費量のコストで。(そして、コードの複雑な> _ <)
しかし、それは、アルゴリズムの実際のメリットを反映していないその時の複雑さについて言っ価値があります。
競争の問題への一般的なあなたがPrim_heapを選択することができ、まばらなグラフであり、彼らはコードが大きすぎると感じた場合、あなたは、プリムとクラスカル法のいずれかを選択クラスカルのアルゴリズムを選択します。