ALDS1_12_A Minimum Spanning Tree

Calendar Clock iconCalendar Clock icon

AOJ

# 目次

# 解答

プリムのアルゴリズム

  1. 3つの配列を頂点数の長さで宣言する
  2. parent[n] ・・・頂点iがMST(最小全域木)に組み込まれた時の接続先頂点.隣接行列と参照して辺とそのコストがわかる。
  3. key[n] ・・・作成中MSTに次に組み込む可能性のある隣接頂点iへのコスト.
  4. mst[n] ・・・頂点がMSTに組み込まれているか否か.最終的にはすべての頂点が組み込まれる。
  5. 最初は頂点0から始めるために、key[0]を0に、その他はありえない最大値に初期化する
  6. MSTは空にする(mstをすべてfalseに)
  7. すべての頂点がMSTに含まれるまで以下を繰り返す(最後の頂点は1つで選択の余地がないので頂点数-1だけ実行)
  8. まだMSTに未追加の隣接頂点のうち、コストが最小であるものをuとし、MSTに加える.
  9. MSTに含まれずuに隣接するすべての頂点vのうち最小コストをkey[v]に格納しvの親をuとする.
  10. すべての辺のコストを隣接行列を参照して合計する.
// C++ 14
#include <iostream>
#include <string>
#include <vector>
#include <list>
#include <algorithm>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <unordered_map>
#include <math.h>

#define ll long long
#define Int int
#define loop(x, start, end) for(Int x = start; x < end; x++)
#define loopdown(x, start, end) for(int x = start; x > end; x--)
#define rep(n) for(int x = 0; x < n; x++)
#define span(a,x,y) a.begin()+x,a.begin()+y
#define span_all(a) a.begin(),a.end()
#define len(x) (x.size())
#define last(x) (*(x.end()-1))

using namespace std;

#define MAX_N 100
#define MAX_INT (1 << 21)


Int prim(Int W[MAX_N][MAX_N], Int n) {
  Int parent[n], key[n];
  bool mst[n];

  loop(i,0,n) key[i] = MAX_INT, mst[i] = false;

  key[0] = 0, parent[0] = -1;
  loop(count,0,n-1) {
    Int u, min_ = MAX_INT;
    loop(i,0,n) {
      if (!mst[i] && key[i] < min_) {
        min_ = key[i], u = i;
      }
    }

    mst[u] = true;

    loop(v,0,n) {
      if (!mst[v] && W[u][v] < key[v]) {
        key[v] = W[u][v], parent[v] = u;
      }
    }
  }

  Int sum_ = 0;
  loop(v,1,n) sum_ += W[v][parent[v]];
  return sum_;
}


int main(void) {
  Int W[MAX_N][MAX_N];
  Int n, w;
  cin >> n;

  loop(u,0,n) {
    loop(v,0,n) {
      cin >> w;
      W[u][v] = W[v][u] = (w == -1) ? MAX_INT : w;
    }
  }

  cout << prim(W, n) << endl;
}

リモートフリーランス。ウェブサービス、スマホアプリエンジニア。
東アジアを拠点に世界を移動しながら活動してます!

お仕事のご依頼・お問い合わせはこちら

コメント