Go: package main

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

const BIG_COST = 3000

const (
	ST_NOT_YET = iota
	ST_JOINED
)

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

	nNodes := scanInt(sc)
	costs := make([][]int, nNodes)

	for r := 0; r < nNodes; r++ {
		costs[r] = make([]int, nNodes)
		for c := 0; c < nNodes; c++ {
			costs[r][c] = scanInt(sc)
		}
	}

	states := make([]int, nNodes)
	minCosts := make([]int, nNodes)

	for i := 1; i < nNodes; i++ {
		minCosts[i] = BIG_COST
	}

	for {
		var u int
		minCost := BIG_COST

		for i := 0; i < nNodes; i++ {
			if states[i] != ST_JOINED && minCosts[i] < minCost {
				minCost = minCosts[i]
				u = i
			}
		}

		// 全てのノードが MST に JOIN できたので終了。
		if minCost == BIG_COST {
			break
		}

		states[u] = ST_JOINED

		for v := 0; v < nNodes; v++ {
			cost := costs[u][v]

			// MST内の u と MST外の v との辺の重みをそれぞれ minCosts[v] として
			// 保存しておく。このうち辺の重みが最小となる v が次のループで MST に JOIN する。
			if states[v] != ST_JOINED && cost != -1 && cost < minCosts[v] {
				minCosts[v] = cost
			}
		}
	}

	sum := 0
	for _, cost := range minCosts {
		sum += cost
	}
	fmt.Println(sum)
}

func scanInt(sc *bufio.Scanner) int {
	sc.Scan()
	v, _ := strconv.Atoi(sc.Text())
	return v
}

C++: #include <bits/stdc++.h>
using namespace std;

struct UnionFind{
  int n;
  vector<int> r, p;
  UnionFind() {}
  UnionFind(int sz): n(sz), r(sz, 1), p(sz, 0){ iota(p.begin(), p.end(), 0); }
  int find(int x) {
    return (x == p[x] ? x : p[x] = find(p[x]));
  }
  bool same(int x, int y) {
    return find(x) == find(y);
  }
  void unite(int x, int y){
    x = find(x); y = find(y);
    if ( x == y ) return;
    if ( r[x] < r[y] ) swap(x, y);
    r[x] += r[y];
    p[y] = x;
  }
};

struct Edge {
  int cost, to, from;
  bool operator<(const Edge& e) const {
    return cost < e.cost;    
  }  
};

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

  vector<Edge> G;
  for ( int i = 0; i < n; i++ ) {
    for ( int j = 0; j < n; j++ ) {
      int cost;
      cin >> cost;
      if ( j > i && cost >= 0 ) G.push_back({cost, i, j});      
    }
  }

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

  UnionFind uf(n);
  int cnt = 0;
  int sum = 0;
  for ( Edge e: G ) {
    int cost = e.cost, to = e.to, from = e.from;
    if ( uf.same(to, from) ) continue;
    sum += cost;
    if ( ++cnt >= n-1 ) break;
    uf.unite(to, from);    
  }

  cout << sum << endl;
  
  return 0;
}

C++: #include<bits/stdc++.h>
using namespace std;
#define int long long

struct edge{ int u,v,cost; };
bool comp(const edge& e1,const edge& e2){
  return e1.cost < e2.cost;
}

vector<edge> es;
int V,E; //頂点数、辺数
const int N = 1e5+10;

struct UF{
  const int N = 1e5+10;
  vector<int> par; //親
  vector<int> depth; //木の深さ

  void init(){
    par.resize(N);
    depth.resize(N);
    for(int i = 0; i < N; i++){
      par[i] = i;
      depth[i] = 0;
    }
  }

  //木の根を求める
  int root(int x){
    if(par[x] == x){
      return x;
    }
    else {
      return par[x] = root(par[x]);
    }
  }

  //xとyの属する集合を併合
  void unite(int x,int y){
    x = root(x);
    y = root(y);
    if(x == y) return;

    if(depth[x] < depth[y]) par[x] = y;
    else {
      par[y] = x;
      if(depth[x] == depth[y]) depth[x]++;
    }
  }
}uf;

int kruskal(){
  sort(es.begin(),es.end(),comp);
  uf.init();
  int min_cost = 0;
  for(int i = 0; i < es.size(); i++){
    edge e = es[i];
    if(e.cost == -1) continue;
    if(uf.root(e.u) != uf.root(e.v)){
      min_cost += e.cost;
      uf.unite(e.u,e.v);
    }
  }
  return min_cost;
}

signed main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  cin >> V;
  for(int i = 0; i < V; i++){
    for(int j = 0; j < V; j++){
      int cost; cin >> cost;
      es.push_back({i,j,cost});
    }
  }
  cout << kruskal() << endl;

  return 0;
}

C++: #include <stdio.h>
#include <iostream>
#include <utility>
#include <algorithm>
#include <math.h>
#include <vector>
using namespace std;

class edge
{
  public:
    int i, j, weigt;
    bool operator()(edge e1, edge e2)
    {
        return e1.weigt < e2.weigt;
    }
};
edge e[10000];
int main()
{
    int n;
    cin >> n;
    int b[n][n] = {};
    int k = 0;
    int tmp = 0;
    int sum = 0;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            cin >> tmp;
            if (j < i + 1 || tmp < 0)
                continue;
            e[k].i = i;
            e[k].j = j;
            e[k].weigt = tmp;
            k++;
        }
    }
    sort(e, e + k, edge());
    for (int i = 0; i < k; i++)
    {
        if (b[e[i].i][e[i].j] == 0)
        {
            sum += e[i].weigt;
            b[e[i].i][e[i].j] = 1;
            b[e[i].j][e[i].i] = 1;
            for (int j = 0; j < n; j++)
            {
                if (b[e[i].i][j] || b[e[i].j][j])
                    b[e[i].i][j] = b[e[i].j][j] = b[j][e[i].i] = b[j][e[i].j] = 1;
            }
        }
    }
    cout << sum << "\n";
    return 0;
}

C++: #define _CRT_SECURE_NO_WARNINGS
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
#include <climits>
#include <list>
#include <queue>

using namespace std;

static const int INFTY = 2001;

int main() {
	int Dist[101];
	int AdjacenceyList[100][100];
	int AdjacenceyWeightList[100][100];
	int Degree[100];
	int i, j;
	int N;
	int W;
	int Deg;
	int MinTotalWeight = 0;
	int u, v;
	int PrevSecondSmallestVertex;
	int SecondSmallestVertex;
	int MinVertex;
	bool inT[100];

	cin >> N;

	for (i = 0; i < N; i++) {
		inT[i] = false;
		Dist[i] = INFTY;
		Deg = -1;
		for (j = 0; j < N; j++) {
			cin >> W;
			if(W != -1){
				AdjacenceyList[i][++Deg] = j;
				AdjacenceyWeightList[i][Deg] = W;
			}
		}
		Degree[i] = Deg + 1;
	}
	Dist[100] = INFTY;

	u = 0;
	inT[u] = true;
	Dist[u] = 0;
	PrevSecondSmallestVertex = 100;
	for (i = 1; i <= N - 1; i++) {
		MinVertex = 100;
		for (j = 0; j < Degree[u]; j++) {
			v = AdjacenceyList[u][j];
			if (inT[v] == false) {
				W = AdjacenceyWeightList[u][j];
				if (W < Dist[v]) {
					Dist[v] = W;
				}
				if (Dist[v] < Dist[MinVertex]) {
					SecondSmallestVertex = MinVertex;
					MinVertex = v;
				}
				else if (Dist[v] < Dist[SecondSmallestVertex]) {
					SecondSmallestVertex = v;
				}
			}
		}

		//DEBUG
		cout << "MinVerTex = " << MinVertex << " SecondSmallestVertex = " << SecondSmallestVertex << endl;

		if (Dist[PrevSecondSmallestVertex] < Dist[MinVertex]) {
			SecondSmallestVertex = MinVertex;
			MinVertex = PrevSecondSmallestVertex;
			PrevSecondSmallestVertex = SecondSmallestVertex;
		}
		else if (Dist[SecondSmallestVertex] < Dist[PrevSecondSmallestVertex]) {
			PrevSecondSmallestVertex = SecondSmallestVertex;
		}
		inT[MinVertex] = true;
		u = MinVertex;
		MinTotalWeight += Dist[MinVertex];

		//DEBUG
		cout << "MinVertex = " << MinVertex << " PrevSecondSmallestVertex = " << PrevSecondSmallestVertex << endl;
		cout << "inT: ";
		for (int k = 0; k < N; k++) {
			cout << inT[k] << " ";
		}
		cout << endl;
		printf("MinTotalWeight = %d\n", MinTotalWeight);
	}
	//printf("%d\n", MinTotalWeight);

	return 0;
}

C++: #include<iostream>
using namespace std;
#define INF  (1<<21)
//int prim(int M[100][100], int n){
int M[100][100];
int prim(int n){
	int u, mincost;
	int color[n], d[n], p[n];
	for(int i=0; i<n; i++){
		color[i]=0;
		d[i]=INF;
		p[i]=-1;
	}
	d[0]=0;
	while(1){
		mincost=INF;
		u=-1;
		for(int i=0; i<n; i++){
			if(mincost>d[i] && color[i]!=2){
				u=i;
				mincost=d[i];
			}
		}
		if(u==-1)
			break;
		color[u]=2;
		for(int v=0; v<n; v++){
			if(color[v]!=2 && M[u][v]!=INF){
				if(d[v]>M[u][v]){
					d[v]=M[u][v];
					p[v]=u;
					color[v]=1;
				}
			}
		}
	}
	int sum=0;
	for(int i=0; i<n; i++)
		if(p[i]!=-1)
			sum+=M[i][p[i]];
	return sum;
}

int main(){
	int n;
	cin>>n;
	//int M[100][100];
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			int e;
			cin>>e;
			if(e!=-1)
				M[i][j]=e;
			else
				M[i][j]=INF;
		}
	}
	cout<<prim(n)<<endl;
	return 0;
}