Go: package main

import (
	"bufio"
	"fmt"
	"log"
	"math"
	"os"
	"strconv"
	"strings"
)

type color int

const (
	white color = iota // 未訪問
	mst                // MSTとして確定
)

// 頂点
type node struct {
	matrix   []int // 隣接行列
	minToMst int   // MSTへの重み最小値
	parent   int   // 最小値の相手
	color    color
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	n := eGetInt(scanner)

	nodes := make([]node, n)
	for i := 0; i < n; i++ {
		nodes[i].matrix = eAtoi((strings.Fields(eGetline(scanner))))
		nodes[i].parent = -1
		nodes[i].minToMst = math.MaxInt16
		nodes[i].color = white
	}

	// 初回はnode[0]がMSTに入るように,minToMstを設定
	nodes[0].minToMst = 0
	for { // 全部チェックするまで

		// どの頂点を新たにMSTに取り込むか
		min := math.MaxInt16
		u := -1
		for i := 0; i < n; i++ {
			if nodes[i].color == mst {
				continue
			}
			if nodes[i].minToMst < min {
				u = i
				min = nodes[i].minToMst
			}
		}

		if u == -1 {
			break
		}
		// MSTに追加する頂点決定
		nodes[u].color = mst

		// MSTに属していない頂点それぞれについて,MSTとの最小の重みを更新
		for i := 0; i < n; i++ {
			if nodes[i].color == mst {
				continue
			}
			if nodes[i].matrix[u] == -1 {
				// 接してない
				continue
			}
			if nodes[i].matrix[u] < nodes[i].minToMst {
				// node[u]との重みが最小
				nodes[i].minToMst = nodes[i].matrix[u]
				nodes[i].parent = u
			}
		}
	}

	sum := 0
	for _, v := range nodes {
		// node[0]はparentが入っていない
		if v.parent != -1 {
			sum += v.matrix[v.parent]
		}
	}
	fmt.Println(sum)
}

func eGetInt(scanner *bufio.Scanner) int {
	t := eAtoi(strings.Fields(eGetline(scanner)))
	return t[0]
}

func eGetline(p *bufio.Scanner) string {
	if !p.Scan() {
		if err := p.Err(); err != nil {
			log.Fatal(err.Error())
		}
		return ""
	}
	return p.Text()
}

func eAtoi(s []string) []int {
	ints := make([]int, len(s))
	var err error
	for i, e := range s {
		ints[i], err = strconv.Atoi(e)
		if err != nil {
			log.Fatal(err.Error())
		}
	}
	return ints
}

C++: #include <iostream>
#include <queue>
#include <vector>

struct Edge {
  int dst;
  long long cost;
  Edge() {}
  Edge(int x, long long y) : dst(x), cost(y) {}
};

int prim(std::vector<std::vector<Edge>> &G) {
  const int V = (int)G.size();
  std::vector<bool> is_used(V, false);

  typedef std::pair<long long, int> PLI;
  std::priority_queue<PLI, std::vector<PLI>, std::greater<PLI>> que;
  que.push(std::make_pair(0LL, 0));

  int ret = 0;
  while (!que.empty()) {
    long long cost = que.top().first;
    int cur_v = que.top().second;
    que.pop();
    if (is_used[cur_v]) {
      continue;
    }
    is_used[cur_v] = true;
    ret += cost;
    for (int i = 0; i < (int)G[cur_v].size(); i++) {
      que.push(std::make_pair(G[cur_v][i].cost, G[cur_v][i].dst));
    }
  }
  return ret;
}

int main() {
  int n;
  std::cin >> n;

  std::vector<std::vector<Edge>> g(n);
  for (int i = 0; i < n; i++) {
    for (int j = 0; j < n; j++) {
      int a;
      std::cin >> a;
      if (a != -1) {
        g[i].push_back(Edge(j, a));
        g[j].push_back(Edge(i, a));
      }
    }
  }
  std::cout << prim(g) << std::endl;

  return 0;
}

C++: #include <bits/stdc++.h>

//{ START
using namespace std;
#define int int64_t
#define rep(i, a, n) for (int i = (a); i < (n); ++i)
#define reps(i, a, n) for (int i = (a); i > (n); --i)
#define arep(i, x) for (auto &&i : (x))
#define irep(i, x) for (auto i = (x).begin(); i != (x).end(); ++i)
//降順はgreater<T>()
#define all(x) (x).begin(), (x).end()
#define rv(s) reverse((s).begin(), (s).end())
//gcd lcmはそのままok
#define gcd(a, b) __gcd(a, b)
#define bits(n) (1 << (n))
#define pcnt(x) __builtin_popcountll(x)
//配列内等要素削除
#define unique(x) (x).erase(unique(x).begin(),(x).end()),(x).end())
#define Fixed(n) fixed << setprecision(n)
//総和
#define sowa(n) ((n) * ((n) + 1)) / 2
#define pb(x, a) (x).push_back(a)
#define fb(x, a) (x).push_front(a)
#define eb(x, a) (x).emplace_back(a)
#define F first
#define S second
#define cauto const auto &
using P = pair<int, int>;
using Graph = vector<vector<P>>;
template <class T> //昇順
using min_heap = priority_queue<T, vector<T>, greater<T>>;
template <class T> //降順
using max_heap = priority_queue<T>;
template <class A, class B>
using umap = unordered_map<A, B>;
template <class A>
using uset = unordered_set<A>;
template <typename A, size_t N, typename T>
void Fill(A (&array)[N], const T &val) //多次元初期化
{
    std::fill((T *)array, (T *)(array + N), val);
}
template <class T>
bool chmax(T &a, const T &b) //最大値更新 返り値はbool
{
    if (a < b)
    {
        a = b;
        return 1;
    }
    return 0;
}
template <class T>
bool chmin(T &a, const T &b) //最小値更新 返り値はbool
{
    if (b < a)
    {
        a = b;
        return 1;
    }
    return 0;
}
int dx[4] = {1, 0, -1, 0};
int dy[4] = {0, 1, 0, -1};
constexpr int INF = 0x3f3f3f3f;
constexpr int LINF = 0x3f3f3f3f3f3f3f3fLL;
constexpr int mod1 = 1e9 + 7;
constexpr int mod2 = 998244353;
//} END

constexpr int MAX_V = 10010;
int cost[MAX_V][MAX_V]; //d[u][v]は辺e=(u,v)のコスト,(存在しないときはINF),d[i][i]=0
int mincost[MAX_V];     //集合xから辺の最小コスト
bool used[MAX_V];       //頂点Iがxに含まれているか
int V;             //頂点数

int prim()
{
    fill(mincost, mincost + V, INF);
    fill(used, used + V, false);
    mincost[0] = 0;
    int res = 0;
    while (true)
    {
        int v = -1;
        //xに属さない頂点のうちxからの辺のコストが最小になる頂点を探す
        rep(u, 0, V)
        {
            if (!used[u] && (v == -1 || mincost[u] < mincost[v]))
                v = u;
        }
        if (v == -1)
            break;
        used[v] = true;    //頂点vをxに追加
        res += mincost[v]; //辺のコストを加える
        rep(u, 0, V) if (cost[v][u] != -1) chmin(mincost[u], cost[v][u]);
    }
    return res;
}

signed main()
{
    cin.tie(nullptr);
    ios_base::sync_with_stdio(false);

    cin >> V;
    rep(i, 0, V) rep(j, 0, V) cin >> cost[i][j];

    cout<<prim()<<'\n';
}

C++: #include <iostream>
#include <list>
#include <utility>
using namespace std;
#define MAXN 100
#define MAXW 2001

int main(){
    int weight[MAXN][MAXN];
    int n; cin >> n;
    for(int i=0; i<n; i++){
        for(int j=0; j<n; j++){
            cin >> weight[i][j];
        }
    }
    
    list<int> MST;
    MST.push_back(0);
    list<int> nonMST;
    for(int i=1; i<n; i++) nonMST.push_back(i);
    
    int weightSum = 0;
    while(!nonMST.empty()){
        int tmpv;
        int tmpWeight = MAXW;
        for(list<int>::iterator it=MST.begin(); it!=MST.end(); it++){
            for(list<int>::iterator it2=nonMST.begin(); it2!=nonMST.end(); it2++){
                if (weight[*it][*it2] < tmpWeight && weight[*it][*it2] != -1){
                    //cout << "tmpWeight update with " << *it2 << endl;
                    tmpWeight = weight[*it][*it2];
                    tmpv = *it2;
                }
            }
        }
        //cout << "MST pushback :" << tmpv << endl; 
        MST.push_back(tmpv);
        nonMST.remove(tmpv);
        weightSum += tmpWeight;
        /*for(list<int>::iterator it=MST.begin(); it!=MST.end(); it++){
            cout << *it << " ";
        }
        cout << endl;
        for(list<int>::iterator it=nonMST.begin(); it!=nonMST.end(); it++){
            cout << *it << " ";
        }
        cout << endl;*/
    }
    
    cout << weightSum << endl;
}