Go: package main

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

// Define disjoint-set forests

type vertexNo int

type vertex struct {
	number vertexNo
	rank int
	parent *vertex
}

func makeSet(number vertexNo) vertex {
	return vertex {
		number: number,
		rank: 0,
		parent: nil,
	}
}

func union(x, y *vertex) *vertex {
	return link(findSet(x), findSet(y))
}

func link(x, y *vertex) *vertex {
	if x.rank > y.rank {
		y.parent = x
		return x
	} else {
		x.parent = y
		if x.rank == y.rank {
			y.rank += 1
		}
		return y
	}
}

func findSet(v *vertex) *vertex {
	if v.parent == nil {
		return v
	}
	v.parent = findSet(v.parent)
	return v.parent
}

// Function to calculate minimum spanning tree

type matrix [][]int

type edge struct {
	one vertexNo
	two vertexNo
	weight int
}

const(
	MAX_VERTICES = 100
)

func newEdgesFromMatrix(matrix matrix) []edge {
	edges := make([]edge, 0, MAX_VERTICES * MAX_VERTICES)

	for i := 0; i < len(matrix); i++ {
		row := matrix[i]
		for j := i; j < len(row); j++ {
			if row[j] >= 0 {
				edge := edge{one: vertexNo(i+1), two: vertexNo(j+1), weight: row[j]}
				edges = append(edges, edge)
			}
		}
	}

	return edges
}

func solve(matrix matrix) int {
	nVertices := len(matrix)

	// initialize vertices
	vertices := make([]vertex, nVertices)
	for i := 0; i < nVertices; i++ {
		vertices[i] = makeSet(vertexNo(i+1))
	}

	// prepare edges sorted in the ascending order of weight
	edges := newEdgesFromMatrix(matrix)
	sort.Slice(edges, func(i, j int) bool {
		return edges[i].weight < edges[j].weight
	})

	unionCount := 0
	weightSum := 0
	for unionCount < nVertices-1 {
		for i := 0; i < len(edges); i++ {
			edge := edges[i]
			v1 := &vertices[edge.one-1]
			v2 := &vertices[edge.two-1]
			rep1 := findSet(v1)
			rep2 := findSet(v2)
			if rep1.number == rep2.number {
				continue
			}
			union(rep1, rep2)
			edges = append(edges[0:i], edges[i+1:]...)
			weightSum += edge.weight
			unionCount++
			break
		}
	}

	return weightSum
}

// main

func main() {
	sc := bufio.NewScanner(os.Stdin)
	sc.Split(bufio.ScanWords)

	n, err := nextInt(sc)
	if err != nil {
		panic(err)
	}

	matrix := parseMatrix(n, sc)

	edges := newEdgesFromMatrix(matrix)
	sort.Slice(edges, func(i, j int) bool {
		return edges[i].weight < edges[j].weight
	})

	fmt.Println(solve(matrix))
}

func parseMatrix(n int, sc *bufio.Scanner) [][]int {
	matrix := make([][]int, n)
	for i := 0; i < n; i++ {
		matrix[i] = make([]int, n)
		for j := 0; j < n; j++ {
			x, err := nextInt(sc)
			if err != nil {
				panic(err)
			}
			matrix[i][j] = x
		}
	}
	return matrix
}

func nextText(sc *bufio.Scanner) string {
	sc.Scan()
	return sc.Text()
}

func nextInt(sc *bufio.Scanner) (int, error) {
	return strconv.Atoi(nextText(sc))
}

C++: #include<iostream>
#include<algorithm>
#define MAX 101
#define INF 1<<21
#define NIL -1
using namespace std;
int n,A[MAX][MAX];
int Minimum_Spanning_Tree(void){
    int color[MAX],d[MAX],vertices,mincost;
    for(int i=0;i<n;i++){
        color[i] = 0;
        d[i] = INF;
    }
    d[0] = 0;
    while(true){
        mincost = INF;
        vertices = NIL;
        for(int i=0;i<n;i++){
            if(color[i]!=1 & d[i]<mincost){
                mincost = d[i];
                vertices = i; 
            }
        }
        if(vertices == NIL){
            break;
        }
        color[vertices] = 1; 
        for(int i=0;i<n;i++){
            if(color[i]!=1 && A[vertices][i] != INF){
                if(A[vertices][i] < d[i]){
                    d[i] = A[vertices][i];
                }
            }
        }
    }
    int sum = 0;
    for(int i=0;i<n;i++){
        sum += d[i];
    }
    return sum;
}
int main(void){
    cin >> n;
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            cin >> A[i][j];
            if(A[i][j] == NIL){
                A[i][j] = INF;
            }
        }
    }
    cout << Minimum_Spanning_Tree() << endl;
    return 0;
}

C++: #include <bits/stdc++.h>
using namespace std;
struct UnionFind{
    vector<int> parent;

    UnionFind(int n) : parent(n){
        for (int i = 0; i < n; i++)parent[i] = i;
    }

    int find(int e){
        if (parent[e] == e) return e;
        else return parent[e] = find(parent[e]);
    }

    void unite (int a, int b) {
        a = find(a);
        b = find(b);
        if (a == b) return;
        parent[a] = b;
    }

    bool same(int a, int b){
        return find(a) == find(b);
    }
};

int main() {
    vector<tuple<int, int, int>> a;
    int n, t, ans = 0;
    cin >> n;
    UnionFind uf(n);
    for(int i = 0; i < n; i++){
        for(int j = 0; j < n; j++){
            cin >> t;
            if (i <= j && t != -1) a.push_back(make_tuple(t,i,j));
        }
    }
    sort(a.begin(), a.end(), [](const tuple<int, int, int>& x, const tuple<int, int, int>& y) { return get<0>(x) < get<0>(y);} );
    for(auto e : a){
        if( !uf.same(get<1>(e), get<2>(e)) ){
            ans += get<0>(e);
            uf.unite(get<1>(e), get<2>(e));
        }
    }
    cout << ans << endl;
}

C++: #include <iostream>

const int MAX = 101;
const int NIL = -1; 
const int UPBOUND = (1 << 20);

using namespace std;

int prim(int adj_matrix[][MAX], int n, int u);


int main()
{
	int adj_matrix[MAX][MAX] = {0};		
	
	int n;
	cin >> n;

	for (int i = 1; i <= n; i++)
	{
		for (int j = 1; j <= n; j++)
		{
			int e; cin >> e;
			adj_matrix[i][j] = e == -1? UPBOUND: e;
		}
	}
	
//	for (int i = 0; i < n; i++)
//	{
//		for (int j = 0; j < n; j++)
//		{
//			cout << adj_matrix[i][j] << " ";
//		}
//		cout << endl;
//	}

	
	cout << prim(adj_matrix, n, 1) << endl;
} 


int prim(int adj_matrix[][MAX], int n, int u)
{
	int cost[MAX]; //记录最小权值
	int edge[MAX]; //记录选中的边
	
	
	for (int v = 1; v <= n; v++)
	{
		cost[v] = adj_matrix[u][v];
		edge[v] = u;
	}	 
	
	cost[u] = NIL; //排除u 
	
	while (true)
	{
		int w = NIL;
		int min = 3000; //权值上限 
		for (int v = 1; v <= n; v++)
		{
			if (cost[v] != NIL && cost[v] < min)
			{
				min = cost[v];
				w = v;
			} 
		}
		
		if (w == NIL) break;
		
		cost[w] = NIL;
		
		//更新最小权值数组 
		for (int v = 1; v <= n; v++)
		{
			if (cost[v] > adj_matrix[w][v] && adj_matrix[w][v] != NIL)
			{
				cost[v] = adj_matrix[w][v];
				edge[v] = w;			
			}
		}
				
	}
	
	
	//求生成树的权值
	int sum = 0;
	for (int v = 1; v <= n; v++)
	{
		if (v != u)
		sum += adj_matrix[v][edge[v]];
	} 
	
	return sum;	
	
}

C++: #include <iostream>
#include <limits>

constexpr int MAXN = 100;
int G[MAXN][MAXN];
int P[MAXN];
int D[MAXN];
int C[MAXN];

int main(){
    int n;
    std::cin >> n;
    for(int i = 0; i < n; i++) {
        for(int j = 0; j < n; j++) {
            std::cin >> G[i][j];
            if (G[i][j] == -1) {
                G[i][j] = std::numeric_limits<int>::max();
            }
        }
    }

    for (int i = 0; i < n; i++) {
        D[i] = std::numeric_limits<int>::max();
    }

    D[0] = 0;
    P[0] = -1;
    while (true) {
        int m;
        int mincost = std::numeric_limits<int>::max();
        for (int i = 0; i < n; i++) {
            if ((C[i] == 0) && (D[i] < mincost)) {
                mincost = D[i];
                m = i;
            }
        }

        if (mincost == std::numeric_limits<int>::max()) {
            break;
        }

        C[m] = 1;
        D[m] = mincost;

        for (int i = 0; i < n; i++) {
            if ((G[m][i] < std::numeric_limits<int>::max()) && (C[i] == 0) && (G[m][i] < D[i])) {
                D[i] = G[m][i];
            }
        }
    }


    int sum = 0;
    for (int i = 0; i < n; i++) {
        if (D[i] != std::numeric_limits<int>::max()) {
            sum += D[i];
        }
    }
//    for (int i = 0; i < n; i++) {
//        std::cout << i << ": " << D[i] << std::endl;
//    }
    std::cout << sum << std::endl;

}