Go: package main

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

const (
	white int = iota
	gray
	black
)
const INFTY int = 2001

var G [][]int
var color []int
var d []int
var p []int
var N int

func prim() int {
	u := 0
	d[u] = 0
	for {
		minCost := INFTY
		for i:=0; i<N; i++ {
			if color[i] != black && d[i] < minCost {
				minCost = d[i]
				u = i
			}
		}

		if minCost == INFTY {
			break
		}

		color[u] = black

		for v:=0; v<N; v++ {
			if color[v] != black && G[u][v] != -1 {
				if G[u][v] < d[v] {
					d[v] = G[u][v]
					p[v] = u
					color[v] = gray
				}
			}
		}
	}
	// sum
	sum := 0
	for i:=0; i<N; i++ {
		if p[i] != -1 {
			sum += G[i][p[i]]
		}
	}
	return sum
}




func initVariable(N int) {
	G = make([][]int, N)
	for i:=0; i<N; i++ {
		G[i] = make([]int, N)
	}
	color = make([]int, N)
	d = make([]int, N)
	p = make([]int, N)
	for i:=0; i<N; i++ {
		d[i] = INFTY
		p[i] = -1
	}
}

func nextInt(scanner *bufio.Scanner) int {
	scanner.Scan()
	num, _ := strconv.Atoi(scanner.Text())
	return num
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	scanner.Split(bufio.ScanWords)
	N = nextInt(scanner)
	initVariable(N)
	for i:=0; i<N; i++ {
		for j:=0; j<N; j++ {
			G[i][j] = nextInt(scanner)
		}
	}
	fmt.Printf("%d\n", prim())
}

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