Go: package main

import (
	"bufio"
	"fmt"
	"log"
	"math"
	"os"
	"strconv"
	"strings"
)

type color int

const (
	white color = iota // 未訪問
	mst                // MSTとして確定
)

// 頂点
type node struct {
	matrix   []int // 隣接行列
	minToMst int   // MSTへの重み最小値
	parent   int   // 最小値の相手
	color    color
}

func main() {
	scanner := bufio.NewScanner(os.Stdin)
	n := eGetInt(scanner)

	nodes := make([]node, n)
	for i := 0; i < n; i++ {
		nodes[i].matrix = eAtoi((strings.Fields(eGetline(scanner))))
		nodes[i].parent = -1
		nodes[i].minToMst = math.MaxInt16
		nodes[i].color = white
	}

	// 初回はnode[0]がMSTに入るように,minToMstを設定
	nodes[0].minToMst = 0
	for { // 全部チェックするまで

		// どの頂点を新たにMSTに取り込むか
		min := math.MaxInt16
		u := -1
		for i := 0; i < n; i++ {
			if nodes[i].color == mst {
				continue
			}
			if nodes[i].minToMst < min {
				u = i
				min = nodes[i].minToMst
			}
		}

		if u == -1 {
			break
		}
		// MSTに追加する頂点決定
		nodes[u].color = mst

		// MSTに属していない頂点それぞれについて,MSTとの最小の重みを更新
		for i := 0; i < n; i++ {
			if nodes[i].color == mst {
				continue
			}
			if nodes[i].matrix[u] == -1 {
				// 接してない
				continue
			}
			if nodes[i].matrix[u] < nodes[i].minToMst {
				// node[u]との重みが最小
				nodes[i].minToMst = nodes[i].matrix[u]
				nodes[i].parent = u
			}
		}
	}

	sum := 0
	for _, v := range nodes {
		// node[0]はparentが入っていない
		if v.parent != -1 {
			sum += v.matrix[v.parent]
		}
	}
	fmt.Println(sum)
}

func eGetInt(scanner *bufio.Scanner) int {
	t := eAtoi(strings.Fields(eGetline(scanner)))
	return t[0]
}

func eGetline(p *bufio.Scanner) string {
	if !p.Scan() {
		if err := p.Err(); err != nil {
			log.Fatal(err.Error())
		}
		return ""
	}
	return p.Text()
}

func eAtoi(s []string) []int {
	ints := make([]int, len(s))
	var err error
	for i, e := range s {
		ints[i], err = strconv.Atoi(e)
		if err != nil {
			log.Fatal(err.Error())
		}
	}
	return ints
}

C++: //#define LOCAL

#include<cstdio>
#include<algorithm>
#include<vector>

using namespace std;

#define rep(a, b) for(int i = a; i <= b; i++)

const int MAX = 1e2 + 10;

struct Ufs
{
	int prt[MAX];

	void init(int n)
	{
		rep(1, n)
			prt[i] = i;
		return;
	}

	int findprt(int x)
	{
		while(x != prt[x])
			x = prt[x];
		return x;
	}

	bool unite(int x, int y)
	{
		int px = findprt(x);
		int py = findprt(y);
		prt[x] = prt[y] = prt[px] = prt[py] = min(px, py);
		return px != py;
	}
};

struct Kruskal
{
	struct Edge
	{
		int u, v, w;
		Edge(int uu, int vv, int ww):u(uu), v(vv), w(ww){}
		friend bool operator <(Edge a, Edge b)
		{
			return a.w < b.w;
		}
	};

	vector<Edge> e;
	Ufs u;

	void init(void)
	{
		e.clear();
		return;
	}

	void addedge(int u, int v, int w)
	{
		e.push_back(Edge(u, v, w));
		return;
	}

	int solve(int n)
	{
		u.init(n);
		int ans = 0, cnt = 0;
		int len = e.size();
		sort(e.begin(), e.end());
		rep(0, len - 1)
		{
			if(u.unite(e[i].u, e[i].v))
			{
				cnt++;
				ans += e[i].w;
			}
			if(cnt == n - 1)
				break;
		}
		return ans;
	}
} k;

int main()
{

#ifdef LOCAL
	freopen("in.txt", "r", stdin);
#endif

	int n;
	while(~scanf("%d", &n))
	{
		k.init();
		rep(1, n)
		{
			for(int j = 1; j <= n; j++)
			{
				int w;
				scanf("%d", &w);
				if(j > i && w != -1)
					k.addedge(i, j, w);
			}
		}
		printf("%d\n", k.solve(n));
	}
	return 0;
}

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

int main(){
  int n;
  int a[100][100],b[100]={},c[100]={};
  cin>>n;
  for(int i=0;i<n;i++)
   for(int j=0;j<n;j++)cin>>a[i][j];
  c[0]=1;

  int k=0.min=10000,min1=0,ans=0;
  while(1){
   if(k==n)break;
   for(int i=0;i<n;i++)
    for(int j=0;j<n;j++)
     if(a[b[i]][j]<min && a[b[i]][j]!=-1 &&c[j]!=1){
      min=a[b[i]][j];
      b[k]=j;
    }
   c[b[k]]=1
   ans+=min;
   k++;
  }
 cout<<ans<<endl;
 return 0;
}

C++: #include <bits/stdc++.h>
#define endl "\n"
using namespace std;

int n;
vector<vector<double>>v;
vector<double>w;
vector<int>pre;
double inf=1e7;
void solve(){
	for(int i=0;i<n;i++)w.push_back(inf);
	for(int i=0;i<n;i++)pre.push_back(-1);
	w[0]=0;
	int k=0;
	double res=0;
	while(k++!=n){
		// 选一个最小的 
		double mi=inf;
		int id=-1;
		for(int i=0;i<n;i++)
			if(w[i]!=-1&&w[i]<mi)mi=w[i],id=i;
		w[id]=-1;
		for(int i=0;i<n;i++){
			if(w[i]!=-1&&v[id][i]!=-1&&v[id][i]<w[i]){
				w[i]=v[id][i];
				pre[i]=id;
			}
		}
		res+=mi;
	}
	cout<<res<<endl;
}
int main(){
	int t;
	cin>>n;
	for(int i=0;i<n;i++){
		v.push_back(vector<double>());
		for(int j=0;j<n;j++){
			cin>>t;
			v[i].push_back(t);
		}
	}
	solve();	
	return 0;
}

C++: // 最小全域木 ( プリム法 )
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<stack>
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>

#include<queue>

using namespace std;

#define MAX_N 100
// 値の定義
const int INV = -1;
const int MAX_W = 2000;

// グラフ情報を保持する配列
int ary_graph[MAX_N + 1][MAX_N + 1];

// グラフを構成する頂点を保持するキュー
queue<int> Base_Queue;

int n = 0;

// プリム法で最小全域木を求める
int MinimumSpanningTree(void);

int main(void)
{
    int sum = 0;

    for(int i = 0; i < MAX_N + 1; i++)
    {
        for(int j = 0; j < MAX_N + 1; j++)
        {
            // 配列の初期化
            ary_graph[i][j] = INV;
        }
    }

    cin >> n;

    for(int i = 0; i < n; i++)
    {
        // グラフを構成する頂点の格納
        Base_Queue.push(i);

        for(int j = 0; j < n; j++)
        {
            // 隣接行列の設定
            cin >> ary_graph[i][j];
        }
    }

    // 頂点１から最小全域木を探索する
    sum = MinimumSpanningTree();

    // 結果の表示
    printf("%d\n", sum);

    return 0;
}

// 最小全域木を探索する関数
int MinimumSpanningTree(void)
{

    int q_size_1, q_size_2, min_val, min_ele, s, t, tmp;
    // 辺の和を保持する変数
    int sum = 0;

    // 最小全域木を構成する頂点を保持するキュー
    queue<int> Prim_Queue;

    // 検索する頂点の初期値の設定
    s = Base_Queue.front();
    Base_Queue.pop();
    Prim_Queue.push(s);

    while( !Base_Queue.empty() )
    {
        // ----------------------------------------------
        // Prim_Queueの頂点 から Base_Queueの頂点への辺の中で
        // 最小コストの辺を検索する方針で進める
        // ----------------------------------------------

        min_val = MAX_W;
        min_ele = INV;

        q_size_1 = Base_Queue.size();
        q_size_2 = Prim_Queue.size();

        for( int i = q_size_2; i > 0; i-- )
        {
            // --- s から t に向かう辺の重みを探索する ---
            s = Prim_Queue.front();
            Prim_Queue.pop();
            // Prim_Queue の要素が減らないように, 取り出したものを元に戻す
            Prim_Queue.push(s);

            for( int i = q_size_1; i > 0; i-- )
            {
                t = Base_Queue.front();
                Base_Queue.pop();

                if( ary_graph[s][t] != INV && min_val > ary_graph[s][t] )
                {
                    // 最小のコストを持つ辺を保存する
                    min_val = ary_graph[s][t];
                    min_ele = t;
                }

                // 取り出したものを, 一旦, 元に戻す
                Base_Queue.push(t);
            }
        }

        // 最小のコストを持つ辺の頂点を追加して
        // 最小全域木を構成する
        for(int i = 0; i < Base_Queue.size(); i++)
        {
            tmp = Base_Queue.front();
            Base_Queue.pop();

            if( tmp == min_ele )
            {
                // 最小コストの辺を持つ頂点を追加する
                Prim_Queue.push(tmp);
                break;
            }
            else
            {
                // 対象外なら元に戻す
                Base_Queue.push(tmp);
            }
        }

        // 辺の和を求める
        sum += min_val;
    }

    return sum;
}