Go: package main

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

func getScanner(fp *os.File) *bufio.Scanner {
	scanner := bufio.NewScanner(fp)
	scanner.Split(bufio.ScanWords)
	scanner.Buffer(make([]byte, 500001), 500000)
	return scanner
}

func getNextString(scanner *bufio.Scanner) string {
	scanner.Scan()
	return scanner.Text()
}

func getNextInt(scanner *bufio.Scanner) int {
	i, _ := strconv.Atoi(getNextString(scanner))
	return i
}

func main() {
	fp := os.Stdin
	if len(os.Args) > 1 {
		fp, _ = os.Open(os.Args[1])
	}

	scanner := getScanner(fp)
	writer := bufio.NewWriter(os.Stdout)

	n := getNextInt(scanner)

	g := make([][]int, n)
	ans := make([][]int, n)

	inf := 1 << 30
	for i := 0; i < n; i++ {
		g[i] = make([]int, n)
		ans[i] = make([]int, n)
		for ii := 0; ii < n; ii++ {
			g[i][ii] = getNextInt(scanner)
			if g[i][ii] == -1 {
				g[i][ii] = inf
			}
			ans[i][ii] = -1
		}
	}

	im := make(IntMap, 1)

	im.increment(1)

	for len(im) < n {
		min := inf
		u := -1
		v := -1
		for i := range im {
			for ii := 0; ii < n; ii++ {
				if im.get(ii) != 0 {
					continue
				}
				if min > g[i][ii] {
					min = g[i][ii]
					u = i
					v = ii
				}
			}
		}
		im.increment(v)
		ans[u][v] = min
		ans[v][u] = min
	}

	sum := 0
	for i := 0; i < n-1; i++ {
		for ii := i + 1; ii < n; ii++ {
			if ans[i][ii] != -1 {
				sum += ans[i][ii]
			}
		}
	}

	fmt.Fprintln(writer, sum)
	writer.Flush()
}

// IntMap ...
type IntMap map[int]int

func (m IntMap) get(key int) int {
	if _, ok := m[key]; ok {
		return m[key]
	}
	return 0
}
func (m IntMap) increment(key int) {
	if _, ok := m[key]; ok == false {
		m[key] = 0
	}
	m[key]++
}

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

const long MAX = 100;
const long INFTY = (1<<21);
const long WHITE = 0;
const long GRAY = 1;
const long BLACK = 2;

long n, M[MAX][MAX];

long prim(){
	long u, minv;
	long d[MAX], p[MAX], color[MAX];

	for (long i = 0; i < n; i++){
		d[i] = INFTY;
		p[i] = -1;
		color[i] = WHITE;
	}

	d[0] = 0;

	while (1){
		minv = INFTY;
		u = -1;
		for (long i = 0; i < n; i++){
			if (minv > d[i] && color[i] != BLACK){
				u = i;
				minv = d[i];
			}
		}
		if (u == -1) break;
		color[u] = BLACK;
		for (long v = 0; v < n; v++){
			if (color[v] != BLACK && M[u][v] != INFTY){
				if (d[v] > M[u][v]){
					d[v] = M[u][v];
					p[v] = u;
					color[v] = GRAY;
				}
			}
		}
	}
	int sum = 0;
	for (long i = 0; i < n; i++){
		if (p[i] != -1) sum += M[i][p[i]];
	}

	return sum;
}

int main(){
	cin >> n;

	for (long i = 0; i < n; i++){
		for (long j = 0; j < n; j++){
			long e;
			cin >> e;
			M[i][j] = (e == -1) ? INFTY : e;
		}
	}

	cout << prim() << endl;
}

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

int n;
int MAXIMUM=100;
int M[100][100];
int INF = 123456789;
// W:未訪問
// G:訪問する候補
// B:訪問済み
int W=0,G=1,B=2;
int prim(){
  int u,minv;
  int d[MAXIMUM],p[MAXIMUM],color[MAXIMUM];
  // d[n]:Tに属する頂点と V - T に属する頂点をつなぐ辺の中で重みが最小の辺の重みを記録

  //初期化
  for(int i=0;i<n;i++){
    d[i]=INF;
    p[i]=-1;
    color[i]=W;
  }

  d[0]=0;

  while (1) {
    minv = INF;
    u = -1;
    //訪問済みでない頂点の中で最もコストが低い辺を探す
    for(int i=0;i<n;i++){
      if(minv>d[i] && color[i]!=B){
        u=i;
        minv=d[i];
      }
    }
    // 頂点が見つからなかったら終了
    if(u==-1) break;
    // 頂点を訪問済に
    color[u] = B;
    //訪問済みでないかつ辺がつながっている頂点の中でコストが最小の辺を選択
    for(int v=0;v<n;v++){
      if(color[v]!=B && M[u][v]!=INF){
        if(d[v]>M[u][v]){
          d[v] =M[u][v];
          p[v] =u;
          color[v]=G;
        }
      }
    }
  }

  int sum=0;
  for(int i=0;i<n;i++){
    if(p[i]!=-1) sum+= M[i][p[i]];
  }
  return sum;
}

int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
      int e;
      cin>>e;
      // M[i][j]=(e==-1) ? INF :e;
      if(e==-1) M[i][j]=INF;
      else M[i][j]=e;
    }
  }

  int ans =prim();
  cout<<ans<<endl;
}

C++: #include<iostream>
using namespace std;
static const int MAX =100;
static const int INFTY=(1<<21);
static const int WHITE=0;
static const int GRAY=1;
static const int BLACK=2;
int n,M[MAX][MAX];
int prim(){
  int u,minv;
  int d[MAX],p[MAX],color[MAX];
  for(int i=0;i<n;i++){
    d[i]=INFTY;
    p[i]=-1;
    color[i]=WHITE;
  }
  d[0]=0;
  while(1){
    minv = INFTY;
    u=-1;
    for(int i=0;i<n;i++){
      if(minv>d[i]&&color[i]!=BLACK){
	u=i;
	minv=d[i];
      }
    }
    if(u==-1)break;
    color[u]=BLACK;
    for(int v=0;v<n;v++){
      if(color[v]!=BLACK&&M[u][v]!=INFTY){
	if(d[v]>M[u][v]){
	  d[v]=M[u][v];
	  p[v]=u;
	  color[v]=GRAY;
	}
      }
    }
  }
  int sum=0;
  for(int i=0;i<n;i++){
    if(p[i]!=-1)sum+=M[i][p[i]];
  }
  return sum;
}
int main(){
  cin>>n;
  for(int i=0;i<n;i++){
    for(int j=0;j<n;j++){
      int e; cin>>e;
      M[i][j]=(e==-1)?INFTY:e;
    }
  }
  cout<<prim()<<endl;
  return 0;
}

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

int n;					//えぬ
int a[100][100] = {0};	//辺の重さ
int f[100] = {0};		//その頂点がすでに連結済みかどうか、その集団の番号
int c = 0;				//全体の重さ
int d = 1;				//次につける集団番号
int s = 0;				//選んだ本数
vector<int> w;			//木のリスト、軽いもの順
int wc = 0;				//見てる木のリストの位置

int main(){
	cin >> n;
	//まず辺の重さをaに入れる
	//wに辺のリストを入れる
	for ( int i = 0; i < n; i++ ) {
		for ( int j = 0; j < n; j++ ) {
			cin >> a[i][j];
			if ( a[i][j] != -1 && i < j ) w.push_back( a[i][j] );
		}
	}
	sort( w.begin(),w.end() );
	while(true) {									//n-1本選ぶまで無限ループ
		for ( int i = 0; i < n - 1; i++ ) {			// i < j を満たすように木を調べ続ける
			for ( int j = i + 1; j < n; j++ ) {
				if ( a[i][j] != w[wc] ) continue;	//その木が一番軽い木だったらそれを対象に検査を始める
				if ( f[i] > 0 && f[j] > 0 ) {		//その木の両端が両方とも連結済みだったら
					if ( f[i] != f[j] ) {
						int y = f[j];
						for ( int x = 0; x < n; x++ ) {
							if ( f[x] == y ) f[x] = f[i];
						}
						c += a[i][j];
						s++;
						cout << i << " " << j << endl;
					}
				}else if ( f[i] == 0 && f[j] == 0 ) {
					f[i] = d;
					f[j] = d;
					d++;
					c += a[i][j];
					s++;
					cout << i << " " << j << endl;
				}else {
					if ( f[i] == 0 ) {
						f[i] = f[j];
						c += a[i][j];
						s++;
					}else {
						f[j] = f[i];
						c += a[i][j];
						s++;
					}
					cout << i << " " << j << endl;
				}
				wc++;
				a[i][j] = -1;
				if ( s == n-1 ) break;
			}
			if ( s == n-1 ) break;
		}
		if ( s == n-1 ) break;
	}
	cout << c << endl;
	return 0;
}

C++: #include<iostream>
#include<vector>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<string>
#include<sstream>
#include<cmath>
#include<numeric>
#include<map>
#include<stack>
#include<queue>
using namespace std;
int inf = 1000000000;

class UF{
public:
  vector<int> u;
  vector<int> r;

  void init(int n){
    u.resize(n, 0);
    r.resize(n, 0);
    for(int i=0; i<n; i++) u[i] = i;
  }
  int root(int x){
    // if( u[x] == x ) return x;
    // else return root(u[x]);
    return u[x] == x ? x : u[x] = root(u[x]);
  }
  bool same(int x, int y){
    return root(x) == root(y);
  }
  void unite(int x, int y){
    x = root(x);
    y = root(y);
    if( x == y ) return;

    if( r[x] < r[y] ){
      u[x] = y;
    }else{
      u[y] = x;
      if( r[x] == r[y] ) r[x]++;
    }
  }
};
class Graph{
public:
  int from, to, cost;
  bool operator<(const Graph &g1)const{
    return g1.cost < cost;
  };
};

int main(void) {

  int n;
  cin >> n;
  UF uf;
  uf.init(n);
  priority_queue<Graph> g;
  for(int i=0; i<n; i++){
    for(int j=0; j<n; j++){
      int a;
      cin >> a;
      if( a == -1 ) continue;
      Graph tg;
      tg.to = i;
      tg.from = j;
      tg.cost = a;
      g.push(tg);
    }
  }

  int sum = 0;
  while( !g.empty() ){
    Graph p = g.top();
    g.pop();

    if( uf.same(p.to, p.from) ) continue;

    sum += p.cost;
    uf.unite(p.to, p.from);

  }
  cout << sum << endl;

  return 0;
}

// EOF