Go: package main

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

var scanner = bufio.NewScanner(os.Stdin)

func nextString() string {
	scanner.Scan()
	return scanner.Text()
}

func nextInt() int {
	n, err := strconv.Atoi(nextString())
	if err != nil {
		fmt.Printf("strconv.Atoi failed: %v\n", err)
	}
	return n
}

type ElementKey int
type Node struct {
	key    ElementKey
	parent *Node
	rank   int
}

func newNode(key ElementKey) *Node {
	node := Node{}
	node.key = key
	node.parent = &node
	node.rank = 0

	return &node
}

func union(x, y *Node) {
	xSet := findSet(x)
	ySet := findSet(y)
	link(xSet, ySet)
}

func link(x, y *Node) {
	if x.rank > y.rank {
		y.parent = x
	} else {
		x.parent = y

		if x.rank == y.rank {
			y.rank++
		}
	}
}

func findSet(x *Node) *Node {
	if x != x.parent {
		x.parent = findSet(x.parent)
	}
	return x.parent
}

func newDisjointSets(nSets int) *DisjointSets {
	sets := DisjointSets{}
	sets.keyToNode = map[ElementKey]*Node{}
	for i := 0; i < nSets; i++ {
		key := ElementKey(i)
		sets.keyToNode[key] = newNode(key)
	}
	return &sets
}

type DisjointSets struct {
	keyToNode map[ElementKey]*Node
}

func (sets *DisjointSets) union(x, y ElementKey) {
	xNode := sets.keyToNode[x]
	yNode := sets.keyToNode[y]
	union(xNode, yNode)
}

func (sets DisjointSets) findSet(x ElementKey) *Node {
	xNode := sets.keyToNode[x]
	return findSet(xNode)
}

type Edge struct {
	i, j   int
	weight int
}

func main() {
	scanner.Split(bufio.ScanWords)

	n := nextInt()
	sets := newDisjointSets(n)
	edges := []Edge{}
	a := make([][]int, n)
	for i := 0; i < n; i++ {
		a[i] = make([]int, n)
		for j := 0; j < n; j++ {
			a[i][j] = nextInt()
			if a[i][j] >= 0 {
				e := Edge{
					i:      i,
					j:      j,
					weight: a[i][j],
				}
				edges = append(edges, e)
			}
		}
	}
	sort.Slice(edges, func(i, j int) bool { return edges[i].weight < edges[j].weight })
	totalWeight := 0
	for _, edge := range edges {
		i := ElementKey(edge.i)
		j := ElementKey(edge.j)
		if sets.findSet(i) != sets.findSet(j) {
			totalWeight += edge.weight
			sets.union(i, j)
		}
	}
	fmt.Println(totalWeight)
}

C++: #include <iostream>
#include <algorithm>
#include <vector>
#include <deque>
#include <queue>
#include <list>
#include <stack>
#include <string>
#include <tuple>
#include <functional>
#include <numeric>
#include <cmath>
#include <iomanip>
#include <map>
#include <random>
#include <cstdlib>
#define INT_MAX 2147483647
#define INT_MIN -2147483646
#define Loop(i, n) for(int i = 0; i < (int)n; i++)
#define Loop1(i, n) for(int i = 1; i <= (int)n; i++)
#define Loopr(i, n) for(int i = (int)n - 1; i >= 0; i--)
#define Loopr1(i, n) for(int i = (int)n; i >= 1; i--)
using namespace std;
typedef long long int ll;
typedef vector<int> vi;
typedef vector<vector<int>> vvi;

static const int N = 105;

struct vertex {
	int id;
	int p;
	int d;
	bool operator<(const vertex & another) const {
		return (d != another.d ? d>another.d : id>another.id);
	}
};

int main() {
	vvi mx(N, vi(N, -1));
	int n;
	cin >> n;
	Loop(i, n) {
		Loop(j, n) {
			int a;
			cin >> a;
			mx[i][j] = a;
		}
	}
	//
	vi color(N, 0); //0,1
	priority_queue<vertex> q;
	q.push({ 0,-1,0});
	int ret = 0;
	while(q.size() > 0) {//?
		vertex v = q.top();
		q.pop();
		if (color[v.id] == 1) continue;
		color[v.id] = 1;
		ret += v.d;
		Loop(j, n) {
			if (mx[v.id][j] != -1 && color[j] != 1){
				q.push({ j, v.id,mx[v.id][j] });
			}
		}
	}
	cout << ret << endl;
	return 0;
}

C++: #if 0
time: 20min
using pair to store the edges' number, making it easier to find their nodes.					
#endif
#include <iostream>
#include <utility>
#include <algorithm>
using namespace std;

int m,n,x,ans;
int P[100+10],edge1[10000+10],edge2[10000+10];


int root(int a){
	if (P[a] == a) return a;
	return (P[a] = root(P[a]));
}

bool same(int a, int b){
	return root(a)==root(b);
}
	
void unite(int a, int b){
	P[root(a)] = root(b);
}

int main() {
	pair<int,int> edges[10000+10];
	cin >> n;
	
	for (int i=1; i<=n; i++){
		P[i] = i;
	}
	
	m = 0;
	for (int i=1; i<=n; i++){
		for (int j=1; j<=n; j++){
			cin >> x;
			if (x>-1){
				edge1[m] = i;
				edge2[m] = j;
				edges[m] = make_pair(x, m);
				m+=1;
			}
		}
	}
	
	sort(edges, edges+m);
	n=1;
	for (int i=0; i<m; i++){
		if (n>=m) break;
		if (!same(edge1[edges[i].second], edge2[edges[i].second])){
			unite(edge1[edges[i].second], edge2[edges[i].second]);
			ans += edges[i].first;
			n+=1;
		}
	}
	
	cout << ans << endl;
	
}

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

int x[10000][10000];
int MIN[10000];
int MINX = 0;
int MINZ = 100;

int main() {
	memset(MIN, 127, sizeof(MIN));
	int n, a;
	cin >> n;
	for (int i = 0; i < n; i++) {
		for (int j = 0; j < n; j++) {
			cin >> a;
			x[i][j] = a;
		}
	}
	for(int h=0;h<n;h++){
		memset(MIN, 127, sizeof(MIN));
		MINX=0;
		MIN[h] = 0;
		for (int i = 0; i < n; i++) {
			for (int j = 0; j < n; j++) {
				for (int k = 0; k < n; k++) {
					if (x[j][k] != -1) {
						MIN[k] = min(MIN[k], x[j][k]);
					}
				}
			}
		}
		for (int i = 0; i < n; i++) {
			MINX += MIN[i];
		}
		MINZ=min(MINZ,MINX);
	}
	cout << MINZ << endl;
	return 0;
}

C++: #include<stdio.h>
#include<queue>
#include<vector>
using namespace std;
const int maxn = 1010;
const int INFTY = 1000000000;
struct Node{
    int to;
    int value;
    void set(int a,int b){
        to  = a;
        value = b;
    }
    void real(){
        value*=-1;
    }
};
bool operator<(const Node&a,const Node &b){
    return a.value<b.value;
}
vector<Node> g[maxn];
priority_queue<Node> q;
int d[maxn];
bool vis[maxn];
int p[maxn];
int n;
void prim(){
    for(int i = 0;i<n;++i){
        d[i] = INFTY;
        vis[i] = false;
        p[i] = -1;
    }
    d[0] = 0;
    Node work;
    work.set(0,0);
    q.push(work);
    while(!q.empty()){
        work = q.top();
        work.real();
        q.pop();
        int from = work.to;
        int len = g[from].size();
        if(vis[from])continue;
        vis[from] = true;
        while(len--){
            int to = g[from][len].to;
            int add = g[from][len].value;
            if(!vis[to]&&(add<d[to])){
                d[to] = add;
                p[to] = from;
                work.set(to,d[to]);
                work.real();
                q.push(work);
            }
        }
    }
}
int main(){
    int tmp,ans;
    Node work;
    scanf("%d",&n);
    for(int i = 0;i<n;++i){
        for(int j  = 0;j<n;++j){
            scanf("%d",&tmp);
            if(tmp!=-1){
                work.set(j,tmp);
                g[i].push_back(work);
            }
        }
    }
    prim();
    ans = 0;
    for(int i = 0;i<n;++i){
        ans+=d[i];
    }
    printf("%d\n",ans);
    return 0;
}

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

using namespace std;

#define INF 2001
#define NIL -2


struct node{
    int key=INF, pi=NIL, flag=0;
};

node grf[101];
int hv[101][101], n;

void search(){
    int min = INF, mini = NIL;
    for(int i=0;i<n;++i){
        if(grf[i].flag != 1 && grf[i].key < min){
            min = grf[i].key;
            mini= i;
        }
    }
    
    if(min == INF){
        return;
    }
    
    grf[mini].flag = 1;
    for(int j=0;j<n;++j){
        if((grf[j].flag != 1 && hv[mini][j] != -1) && hv[mini][j] < grf[j].key){
            grf[j].key = hv[mini][j];
            grf[j].pi = mini;
        }
    }
    
    return;
    
}

int main(){
    int total=0;
    cin >> n;
    for(int i=0;i<n;++i){
        for(int j=0;j<n;++j){
            cin >> hv[i][j];
        }
    }
    
    grf[0].key = 0;
    grf[0].flag = 1;
    for(int j=0;j<n;++j){
        if(hv[0][j] != -1 && hv[0][j] < grf[j].key){
            grf[j].key = hv[0][j];
            grf[j].pi = 0;
        }
    }
    
    for(int i=1;i<n;++i){
        search();
    }
    
    for(int i=0;i<n;++i){
        total+=grf[i].key;
    }
    
    cout << total << endl;
    
    return 0;
}