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++: # if 0
2次元配列の扱いの取り扱いに慣れておらず、2時間ほど時間がかかった。
# endif
#include <iostream>
#include <algorithm>
using namespace std;
int P[10000];
void init(int N) {
  for (int i = 0; i < N; i++) {
    P[i] = i;
  }
}

int root(int a) {
  if(P[a] == a)
    return a;
  return (P[a] = root(P[a]));
}

bool is_same_set(int a, int b) {
  return root(a) == root(b);
}

void unite(int a, int b) {
  P[root(a)] = root(b);
}

int main()
{
  int N;
  cin >> N;
  int A[N][N];
  for (int i = 0; i < N; i++) {
    for (int j = 0; j < N; j++) {
      int x;
      cin >> x;
      A[j][i] = x;
    }
  }
  int cost[10000], src[10000], dst[10000];
  int M = 0;
  for (int r = 0; r < N; r++)
  {
    for (int c = r + 1; c < N; c++)
    {
      if (A[r][c] > -1)
      {
        cost[M] = A[r][c];
        src[M] = r;
        dst[M] = c;
        M += 1;
      }
    }
  }
  init(N);
  pair<int, pair<int, int> > edges[M + 1];
  for (int m = 0; m < M; m++)
  {
    edges[m] = make_pair(cost[m], make_pair(src[m], dst[m]));
  }
  sort(edges, edges+M);
  int sum = 0;
  for (int i=0; i<M; i++) {
    if (is_same_set(edges[i].second.first, edges[i].second.second))
      continue;
    unite(edges[i].second.first, edges[i].second.second);
    sum += edges[i].first;
  }
  cout << sum << endl;
}

C++: #include<iostream>
#include<cstdio>
#include<string>
#include<algorithm>

#define INF 2001
#define MAX 101

using namespace std;

int MAT[MAX][MAX];
int N;

int prim(){
    int sum;
    bool complete[MAX];
    int dist[MAX];
    int parent[MAX];
    
    for (int i = 0; i < N; i++) {
        complete[i] = false;
        dist[i] = INF;
        parent[i] = -1;
    }
    
    dist[0] = 0;
    
    while (1) {
        int u = -1;
        int min = INF;
        
        for (int i = 0; i < N; i++) {
            if (min > dist[i] && !complete[i]) {
                u = i;
                min = dist[i];
            }
        }
        
        if (u == -1) break;
        
        complete[u] = true;
        
        for (int v = 0; v < N; v++) {
            if (!complete[v] && MAT[u][v] != INF) {
                if (dist[v] > MAT[u][v]) {
                    dist[v] = MAT[u][v];
                    parent[v] = u;
                }
            }
        }
    }
    
    sum = 0;
    
    for (int i = 1; i < N; i++) {
        sum += MAT[parent[i]][i];
    }
    
    return sum;
}

int main(){
    cin >> N;
    for (int i = 0; i < N; i++) {
        for (int j = 0; j < N; j++) {
            scanf("%d",&MAT[i][j]);
            if (MAT[i][j] == -1) MAT[i][j] = INF;
        }
    }
    
    cout << prim() << endl;
    
    return 0;
}

C++: #include<iostream>
#include<algorithm>
#include<vector>
#include<functional>
using namespace std;

#if 0
所用時間:

感想:

#endif

int N, buff, M = 0, SUM = 0, A[101][101], cost[5000], dpt[5000], dst[5000], P[100001]; //A[Y][X]
vector<pair<int, int> > edges;

void init(int N){ //木構造の初期化
  for(int i = 0; i <= N; ++i){
    P[i] = i;
  }
}

int root(int a){ //根の参照
  if(P[a] == a) return a;
  return (P[a] = root(P[a]));
}

bool is_same_set(int a, int b){ //同じ根か?
  return root(a) == root(b);
}

void unite(int a, int b){
  P[root(a)] = root(b); //aのrootをbの子にする
}

void preprocess(){//辺の前処理
  for(int r = 0; r < N; ++r){
    for(int c = r+1; c < N; ++c){
      if (A[r][c] > -1) {
        cost[M] = A[r][c];
        dpt[M] = r;
        dst[M] = c;
        M++;
      }
    }
  }

  //for(int i = 0; i < M; ++i) cout << cost[i] << endl;

  for(int i = 0; i < M; ++i){
    edges.push_back(make_pair(cost[i], i));
  }
  // for(int i = 0; i < M; ++i) cout << edges[i].first << " " << edges[i].second << endl;

  sort(edges.begin(), edges.end());

  // for(int i = 0; i < M; ++i) cout << edges[i].first << " " << edges[i].second << endl;

}

void solve(){
  int ans = 0;
  preprocess();

  init(N);

  for(int i = 0; i < M; ++i){
    int index = edges[i].second;
    if(is_same_set(dpt[index], dst[index])) continue;
    else {
      unite(dpt[index], dst[index]);
      ans += cost[index];
    }
  }
  cout << ans << endl;
}

int main(){

cin >> N;

for(int i = 0; i < N; ++i){
  for(int j = 0; j < N; ++j){
    cin >> buff;
    A[i][j] = buff;
    }
  }

  //行列の表示
  // cout << "Matrix:" << endl;
  // for(int row=0; row < N; ++row){
  //   for(int col = 0; col < N; ++col){
  //     cout << A[row][col];
  //   }
  //   cout << endl;
  // }

  solve();
}