Go: package main

import (
	"bufio"
	"fmt"
	"os"
	"sort"
	"strconv"
)

var scanner = bufio.NewScanner(os.Stdin)

func nextString() string {
	scanner.Scan()
	return scanner.Text()
}

func nextInt() int {
	n, err := strconv.Atoi(nextString())
	if err != nil {
		fmt.Printf("strconv.Atoi failed: %v\n", err)
	}
	return n
}

type ElementKey int
type Node struct {
	key    ElementKey
	parent *Node
	rank   int
}

func newNode(key ElementKey) *Node {
	node := Node{}
	node.key = key
	node.parent = &node
	node.rank = 0

	return &node
}

func union(x, y *Node) {
	xSet := findSet(x)
	ySet := findSet(y)
	link(xSet, ySet)
}

func link(x, y *Node) {
	if x.rank > y.rank {
		y.parent = x
	} else {
		x.parent = y

		if x.rank == y.rank {
			y.rank++
		}
	}
}

func findSet(x *Node) *Node {
	if x != x.parent {
		x.parent = findSet(x.parent)
	}
	return x.parent
}

func newDisjointSets(nSets int) *DisjointSets {
	sets := DisjointSets{}
	sets.keyToNode = map[ElementKey]*Node{}
	for i := 0; i < nSets; i++ {
		key := ElementKey(i)
		sets.keyToNode[key] = newNode(key)
	}
	return &sets
}

type DisjointSets struct {
	keyToNode map[ElementKey]*Node
}

func (sets *DisjointSets) union(x, y ElementKey) {
	xNode := sets.keyToNode[x]
	yNode := sets.keyToNode[y]
	union(xNode, yNode)
}

func (sets DisjointSets) findSet(x ElementKey) *Node {
	xNode := sets.keyToNode[x]
	return findSet(xNode)
}

type Edge struct {
	i, j   int
	weight int
}

func main() {
	scanner.Split(bufio.ScanWords)

	n := nextInt()
	sets := newDisjointSets(n)
	edges := []Edge{}
	a := make([][]int, n)
	for i := 0; i < n; i++ {
		a[i] = make([]int, n)
		for j := 0; j < n; j++ {
			a[i][j] = nextInt()
			if a[i][j] >= 0 {
				e := Edge{
					i:      i,
					j:      j,
					weight: a[i][j],
				}
				edges = append(edges, e)
			}
		}
	}
	sort.Slice(edges, func(i, j int) bool { return edges[i].weight < edges[j].weight })
	totalWeight := 0
	for _, edge := range edges {
		i := ElementKey(edge.i)
		j := ElementKey(edge.j)
		if sets.findSet(i) != sets.findSet(j) {
			totalWeight += edge.weight
			sets.union(i, j)
		}
	}
	fmt.Println(totalWeight)
}

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;
}