Problem:
Minimum Spanning Tree
For a given weighted graph $G = (V, E)$, find the minimum spanning tree (MST) of $G$ and print total weight of edges belong to the MST.
Input
In the first line, an integer $n$ denoting the number of vertices in $G$ is given. In the following $n$ lines, a $n \times n$ adjacency matrix $A$ which represents $G$ is given.
$a_{ij}$ denotes the weight of edge connecting vertex $i$ and vertex $j$. If there is no edge between $i$ and $j$, $a_{ij}$ is given by -1.
Output
Print the total weight of the minimum spanning tree of $G$.
Constraints
$1 \leq n \leq 100$
$0 \leq a_{ij} \leq 2,000$ (if $a_{ij} \neq -1$)
$a_{ij} = a_{ji}$
$G$ is a connected graph
Sample Input 1
5
 -1 2 3 1 -1
 2 -1 -1 4 -1
 3 -1 -1 1 1
 1 4 1 -1 3
 -1 -1 1 3 -1
Sample Output 1
5
Reference
Introduction to Algorithms, Thomas H. Cormen, Charles E. Leiserson, Ronald L. Rivest, and Clifford Stein. The MIT Press.

Submitted solutions:

code_snippet: #include <iostream>
#include <algorithm>
#include <map>
#include <vector>

using namespace std;

map<int, vector<int>> vertex;
map<int, vector<int>> edge;
int sum = 0;

struct UnionFind {
    vector<int> parent, rank;

    UnionFind(int n) {
        parent.resize(n + 1);
        rank.resize(n + 1, 0);
        for (int i = 0; i <= n; i++) parent[i] = i;
    }

    int find(int x) {
        if (parent[x] != x) parent[x] = find(parent[x]);
        return parent[x];
    }

    bool unite(int x, int y) {
        int rx = find(x);
        int ry = find(y);
        if (rx == ry) return false;
        if (rank[rx] < rank[ry]) {
            parent[rx] = ry;
        } else {
            parent[ry] = rx;
            if (rank[rx] == rank[ry]) rank[rx]++;
        }
        return true;
    }
};

void explore(int weight, int N, UnionFind &uf) {
    bool updated = false;

    for (int i = 1; i <= N; i++) {
        int counter = 0;
        for (int w : edge[i]) {
            if (w == weight) {
                int u = i;
                int v = vertex[i][counter];

                if (uf.unite(u, v)) {
                    sum += weight;
                    // cout << u << " - " << v << " : " << weight << endl;
                    updated = true;
                }
            }
            counter++;
        }
    }

    if (updated) explore(weight + 1, N, uf);  // まだ更新があれば次へ
    else if (weight <= 10000) explore(weight + 1, N, uf);  // 一応探索を続ける
}

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

    vector<vector<int>> matrix(N, vector<int>(N));
    for (int i = 0; i < N; i++)
        for (int j = 0; j < N; j++)
            cin >> matrix[i][j];

    // vertex と edge の構築（上三角のみ）
    for (int i = 0; i < N - 1; i++) {
        for (int j = i + 1; j < N; j++) {
            if (matrix[i][j] != -1) {
                vertex[i + 1].push_back(j + 1);
                edge[i + 1].push_back(matrix[i][j]);
            }
        }
    }

    UnionFind uf(N);
    explore(1, N, uf);
    cout << sum << endl;

    return 0;
}
accuracy: 0.8333333333333334
time_ms: 20
memory_kb: 5660
final_rank: 10

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Route
{
    int start = -1;
    int end = -1;
    int cost = -1;

    Route(int s, int e, int c)
    {
        start = s;
        end = e;
        cost = c;
    }

    bool operator<(const Route &another) const
    {
        return cost < another.cost;
    }

    bool operator==(const Route &another) const
    {
        return (start == another.start && end == another.end) || (start == another.end && end == another.start);
    }
};

int main()
{
    int n;
    cin >> n;
    vector<Route> routes;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int num;
            cin >> num;
            if (num != -1)
            {
                Route r(i, j, num);
                if (!count(routes.begin(), routes.end(), r))
                {
                    routes.push_back(r);
                }
            }
        }
    }
    // コストでソート
    sort(routes.begin(), routes.end());

    int costSum = 0;
    vector<int> routeGroup(n, -1);
    int groupNum = 0;
    for (Route route : routes)
    {
        // 両方グループ化されていないなら、グループに設定
        if (routeGroup[route.start] == -1 && routeGroup[route.end] == -1)
        {
            routeGroup[route.start] = groupNum;
            routeGroup[route.end] = groupNum;
            groupNum++;
            costSum += route.cost;
        }
        // 同じグループならスキップ
        else if (routeGroup[route.start] == routeGroup[route.end])
        {
            continue;
        }
        else
        {
            // 片方だけグループ化されていない場合は、もう片方のグループに追加
            if (routeGroup[route.start] == -1)
            {
                routeGroup[route.start] = routeGroup[route.end];
            }
            else if (routeGroup[route.end] == -1)
            {
                routeGroup[route.end] = routeGroup[route.start];
            }
            // 別々のグループの場合は、start のグループの番号に変更
            else
            {
                int targetNumber = routeGroup[route.end];
                // end と同じグループだったものも start のグループ番号に変更
                for (int &number : routeGroup)
                {
                    if (number == targetNumber)
                    {
                        number = routeGroup[route.start];
                    }
                }
            }
            costSum += route.cost;
        }
    }
    cout << costSum << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3440
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Route
{
    int start = -1;
    int end = -1;
    int cost = -1;

    Route(int s, int e, int c)
    {
        start = s;
        end = e;
        cost = c;
    }

    bool operator<(const Route &another) const
    {
        return cost < another.cost;
    }

    bool operator==(const Route &another) const
    {
        return (start == another.start && end == another.end) || (start == another.end && end == another.start);
    }
};

int main()
{
    int n;
    cin >> n;
    vector<Route> routes;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int num;
            cin >> num;
            if (num != -1)
            {
                Route r(i, j, num);
                if (!count(routes.begin(), routes.end(), r))
                {
                    routes.push_back(r);
                }
            }
        }
    }
    // コストでソート
    sort(routes.begin(), routes.end());

    int costSum = 0;
    vector<int> routeGroup(n, -1);
    int groupNum = 0;
    for (Route route : routes)
    {
        if (routeGroup[route.start] == -1 && routeGroup[route.end] == -1)
        {
            routeGroup[route.start] = groupNum;
            routeGroup[route.end] = groupNum;
            groupNum++;
            costSum += route.cost;
        }
        else if (routeGroup[route.start] == routeGroup[route.end])
        {
            continue;
        }
        else
        {
            if (routeGroup[route.start] == -1)
            {
                routeGroup[route.start] = routeGroup[route.end];
            }
            else if (routeGroup[route.end] == -1)
            {
                routeGroup[route.end] = routeGroup[route.start];
            }
            else
            {
                int targetNumber = routeGroup[route.end];
                for (int &number : routeGroup)
                {
                    if (number == targetNumber)
                    {
                        number = routeGroup[route.start];
                    }
                }
            }
            costSum += route.cost;
        }
    }
    cout << costSum << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3436
final_rank: 4

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct Route
{
    int start = -1;
    int end = -1;
    int cost = -1;

    Route(int s, int e, int c)
    {
        start = s;
        end = e;
        cost = c;
    }

    bool operator<(const Route &another) const
    {
        return cost < another.cost;
    }

    bool operator==(const Route &another) const
    {
        return (start == another.start && end == another.end) || (start == another.end && end == another.start);
    }
};

int main()
{
    int n;
    cin >> n;
    vector<Route> routes;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            int num;
            cin >> num;
            if (num != -1)
            {
                Route r(i, j, num);
                if (!count(routes.begin(), routes.end(), r))
                {
                    routes.push_back(r);
                }
            }
        }
    }
    sort(routes.begin(), routes.end());
    vector<vector<bool>> routeMap(n);
    for (int i = 0; i < n; i++)
    {
        routeMap[i].resize(n);
    }
    int costSum = 0;
    for (Route r : routes)
    {
        if (routeMap[r.start][r.end])
            continue;
        routeMap[r.start][r.end] = true;
        routeMap[r.end][r.start] = true;
        for (int i = 0; i < n; i++)
        {
            if (routeMap[i][r.start])
            {
                for (int j = 0; j < n; j++)
                {
                    if (routeMap[r.end][j])
                    {
                        routeMap[i][j] = true;
                        routeMap[j][i] = true;
                    }
                }
                routeMap[i][r.end] = true;
                routeMap[r.end][i] = true;
            }
            if (routeMap[i][r.end])
            {
                if (routeMap[i][r.end])
                {
                    for (int j = 0; j < n; j++)
                    {
                        if (routeMap[r.start][j])
                        {
                            routeMap[i][j] = true;
                            routeMap[j][i] = true;
                        }
                    }
                }
                routeMap[i][r.start] = true;
                routeMap[r.start][i] = true;
            }
        }
        costSum += r.cost;
    }

    cout << costSum << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3440
final_rank: 5

code_snippet: #include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

struct route
{
    int start = -1;
    int end = -1;
    int cost = -1;

    route(int s, int e, int c) {
        start = s;
        end = e;
        cost = c;
    }

    bool operator<(const route& another) const {
        return cost < another.cost;
    }

    bool operator==(const route& another) const {
        return (start == another.start && end == another.end)
                || (start == another.end && end == another.start);
    }
};

/*
    道を昇順で登録
    ab(1) cd(2) ac(3) ... など
    サイクルになる場合は除外
    ab cd ac bd(×)
*/

int main()
{
    int n;
    cin >> n;
    vector<route> routes;
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++) {
            int num;
            cin >> num;
            if (num != -1) {
                route r(i, j, num);
                if (!count(routes.begin(), routes.end(), r)) {
                    routes.push_back(r);
                }
            }
        }
    }
    sort(routes.begin(), routes.end());
    vector<vector<bool>> routeMap(n);
    for (int i=0;i<n;i++) {
        routeMap[i].resize(n);
    }
    int costSum = 0;
    // ループチェック
    // 
    for (route r: routes) {
        if (routeMap[r.start][r.end])
            continue;
        routeMap[r.start][r.end] = true;
        routeMap[r.end][r.start] = true;
        for (int i=0;i<n;i++){
            if (routeMap[i][r.start]) {
                for (int j = 0; j < n; j++) {
                    if (routeMap[r.end][j]) {
                        routeMap[i][j] = true;
                        routeMap[j][i] = true;
                    }
                }
                routeMap[i][r.end] = true;
                routeMap[r.end][i] = true;
            }
            if (routeMap[i][r.end]) {
                if (routeMap[i][r.end]) {
                    for (int j = 0; j < n; j++) {
                        if (routeMap[r.start][j]) {
                            routeMap[i][j] = true;
                            routeMap[j][i] = true;
                        }
                    }
                }
                routeMap[i][r.start] = true;
                routeMap[r.start][i] = true;
            }
        }
        costSum += r.cost;
    }

    cout << costSum << endl;
}
accuracy: 1
time_ms: 10
memory_kb: 3372
final_rank: 1

code_snippet: #include <iostream>
using namespace std;

const int MAX_N = 100;
int p[MAX_N];
int r[MAX_N];

void init(int n)
{
    for(int i=0; i<n; i++){
        p[i] = i;
        r[i] = 0;
    }
}

int find(int x)
{
    if(p[x]==x){
        return x;
    }
    else{
        p[x] = find(p[x]);
        return p[x];
    }
}

void unite(int x, int y)
{
    x = find(x);
    y = find(y);

    if(x==y){
        return;
    }
    if(r[x]<r[y]){
        p[x] = y;
    }
    else{
        p[y] = x;
        if(r[x]==r[y]){
            r[x]++;
        }
    }
}

bool same(int x, int y)
{
    return (find(x)==find(y));
}

struct edge{
    int u, v, w;
};

const int MAX_E = 5000;

struct edge E[MAX_E];

int kruskal(int m, int n)
{
    for(int i=0; i<m-1; i++){
        for(int j=i+1; j<m; j++){
            if(E[i].w>E[j].w){
                swap(E[i], E[j]);
            }
        }
    }

    init(n);

    int sum = 0;

    for(int i=0; i<m; i++){
        if(!same(E[i].u, E[i].v)){
            unite(E[i].u, E[i].v);
            sum += E[i].w;
        }
    }
    return sum;
}

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

int G[100][100];

for(int i=0; i<n; i++){
    for(int j=0; j<n; j++){
        cin >> G[i][j];
    }
}

int m = 0;

for(int i=0; i<n; i++){
    for(int j=i+1; j<n; j++){
        if(G[i][j]!=-1){
            E[m].u = i;
            E[m].v = j;
            E[m].w = G[i][j];
            m++;
        }
    }
}

cout << kruskal(m, n) << endl;

return 0;

}
accuracy: 1
time_ms: 10
memory_kb: 3384
final_rank: 3

code_snippet: // 2025/01/29 Tazoe
#include <iostream>
using namespace std;
const int MAX_N = 100; // 最大要素数
int p[MAX_N]; // 親
int r[MAX_N]; // 木の深さ
// n要素で初期化
void init(int n)
{
for(int i=0; i<n; i++){
p[i] = i; // 根のときには親の代りに集合名（根）
r[i] = 0;
}
}
// 集合名（根）を求める
int find(int x)
{
if(p[x]==x){ // 根だったら
return x;
}
else{
p[x] = find(p[x]); // 路の圧縮
return p[x];
}
}
// xとyの属する集合を併合
void unite(int x, int y)
{
x = find(x); // 集合名（根）
y = find(y);
if(x==y){
return;
}
if(r[x]<r[y]){
p[x] = y;
}
else{
p[y] = x;
if(r[x]==r[y]){
r[x]++;
}
}
}
// xとyが同じ集合に属するか否か
bool same(int x, int y)

{
return (find(x)==find(y));
}
struct edge{
int u, v, w;
};
const int MAX_E = 5000;
struct edge E[MAX_E];
int kruskal(int m, int n) // nは頂点数，mは辺数
{
// 辺の配列Eを重みwでソートする
for(int i=0; i<m-1; i++){
for(int j=i+1; j<m; j++){
if(E[i].w>E[j].w){
swap(E[i], E[j]);
}
}
}
init(n); // union-findのデータ構造の初期化
int sum = 0; // 辺の重みの総和
for(int i=0; i<m; i++){
if(!same(E[i].u, E[i].v)){
unite(E[i].u, E[i].v);
sum += E[i].w;
}
}
return sum;
}
int main()
{
int n; // 頂点数
cin >> n;
int G[100][100];
for(int i=0; i<n; i++){
for(int j=0; j<n; j++){
cin >> G[i][j];
}
}
int m = 0; // 辺数
for(int i=0; i<n; i++){
for(int j=i+1; j<n; j++){

if(G[i][j]!=-1){
E[m].u = i;
E[m].v = j;
E[m].w = G[i][j];
m++;
}
}
}
cout << kruskal(m, n) << endl;
return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3376
final_rank: 2

code_snippet: // 2025/01/29 Tazoe

#include <iostream>
using namespace std;

const int MAX_N = 100;	// 最大要素数

int p[MAX_N];			// 親
int r[MAX_N];			// 木の深さ


// n要素で初期化
void init(int n)
{
	for(int i=0; i<n; i++){
		p[i] = i;				// 根のときには親の代りに集合名（根）
		r[i] = 0;
	}
}

// 集合名（根）を求める
int find(int x)
{
	if(p[x]==x){			// 根だったら
		return x;
	}
	else{
		p[x] = find(p[x]);		// 路の圧縮
		return p[x];
	}
}

// xとyの属する集合を併合
void unite(int x, int y)
{
	x = find(x);			// 集合名（根）
	y = find(y);
	if(x==y){
		return;
	}
	
	if(r[x]<r[y]){
		p[x] = y;
	}
	else{
		p[y] = x;
		if(r[x]==r[y]){
			r[x]++;
		}
	}
}

// xとyが同じ集合に属するか否か
bool same(int x, int y)
{
	return (find(x)==find(y));
}


struct edge{
	int u, v, w;
};

const int MAX_E = 5000;

struct edge E[MAX_E];


int kruskal(int m, int n)	// nは頂点数，mは辺数
{
	// 辺の配列Eを重みwでソートする
	for(int i=0; i<m-1; i++){
		for(int j=i+1; j<m; j++){
			if(E[i].w>E[j].w){
				swap(E[i], E[j]);
			}
		}
	}
	
	init(n);				// union-findのデータ構造の初期化
	int sum = 0;			// 辺の重みの総和
	
	for(int i=0; i<m; i++){
		if(!same(E[i].u, E[i].v)){
			unite(E[i].u, E[i].v);
			sum += E[i].w;
		}
	}
	
	return sum;
}


int main()
{
	int n;							// 頂点数
	cin >> n;
	
	int G[100][100];
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			cin >> G[i][j];
		}
	}
	
	int m = 0;						// 辺数
	for(int i=0; i<n; i++){
		for(int j=i+1; j<n; j++){
			if(G[i][j]!=-1){
				E[m].u = i;
				E[m].v = j;
				E[m].w = G[i][j];
				m++;
			}
		}
	}
	
	cout << kruskal(m, n) << endl;
	
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3484
final_rank: 8

code_snippet: // 2025/01/29 Tazoe

#include <iostream>
using namespace std;

const int MAX_N = 100;	// 最大要素数

int p[MAX_N];			// 親
int r[MAX_N];			// 木の深さ


// n要素で初期化
void init(int n)
{
	for(int i=0; i<n; i++){
		p[i] = i;				// 根のときには親の代りに集合名（根）
		r[i] = 0;
	}
}

// 集合名（根）を求める
int find(int x)
{
	if(p[x]==x){			// 根だったら
		return x;
	}
	else{
		p[x] = find(p[x]);		// 路の圧縮
		return p[x];
	}
}

// xとyの属する集合を併合
void unite(int x, int y)
{
	x = find(x);			// 集合名（根）
	y = find(y);
	if(x==y){
		return;
	}
	
	if(r[x]<r[y]){
		p[x] = y;
	}
	else{
		p[y] = x;
		if(r[x]==r[y]){
			r[x]++;
		}
	}
}

// xとyが同じ集合に属するか否か
bool same(int x, int y)
{
	return (find(x)==find(y));
}


struct edge{
	int u, v, w;
};

const int MAX_E = 10000;

struct edge E[MAX_E];


int kruskal(int m, int n)	// nは頂点数，mは辺数
{
	// 辺の配列Eを重みwでソートする
	for(int i=0; i<m-1; i++){
		for(int j=i+1; j<m; j++){
			if(E[i].w>E[j].w){
				swap(E[i], E[j]);
			}
		}
	}
	
	init(n);				// union-findのデータ構造の初期化
	int sum = 0;			// 辺の重みの総和
	
	for(int i=0; i<m; i++){
		if(!same(E[i].u, E[i].v)){
			unite(E[i].u, E[i].v);
			sum += E[i].w;
		}
	}
	
	return sum;
}


int main()
{
	int n;							// 頂点数
	cin >> n;
	
	int G[100][100];
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			cin >> G[i][j];
		}
	}
	
	int m = 0;						// 辺数
	for(int i=0; i<n; i++){
		for(int j=i+1; j<n; j++){
			if(G[i][j]!=-1){
				E[m].u = i;
				E[m].v = j;
				E[m].w = G[i][j];
				m++;
			}
		}
	}
	
	cout << kruskal(m, n) << endl;
	
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3444
final_rank: 7

code_snippet: // 2025/01/29 Tazoe

#include <iostream>
using namespace std;

const int MAX_N = 100;	// 最大要素数

int p[MAX_N];			// 親
int r[MAX_N];			// 木の深さ


// n要素で初期化
void init(int n)
{
	for(int i=0; i<n; i++){
		p[i] = i;				// 根のときには親の代りに集合名（根）
		r[i] = 0;
	}
}

// 集合名（根）を求める
int find(int x)
{
	if(p[x]==x){			// 根だったら
		return x;
	}
	else{
		p[x] = find(p[x]);		// 路の圧縮
		return p[x];
	}
}

// xとyの属する集合を併合
void unite(int x, int y)
{
	x = find(x);			// 集合名（根）
	y = find(y);
	if(x==y){
		return;
	}
	
	if(r[x]<r[y]){
		p[x] = y;
	}
	else{
		p[y] = x;
		if(r[x]==r[y]){
			r[x]++;
		}
	}
}

// xとyが同じ集合に属するか否か
bool same(int x, int y)
{
	return (find(x)==find(y));
}


struct edge{
	int u, v, w;
};

const int MAX_E = 10000;

struct edge E[MAX_E];


int kruskal(int m, int n)	// nは頂点数，mは辺数
{
	// 辺の配列Eを重みwでソートする
	for(int i=0; i<m-1; i++){
		for(int j=i+1; j<m; j++){
			if(E[i].w>E[j].w){
				swap(E[i], E[j]);
			}
		}
	}
	
	init(n);				// union-findのデータ構造の初期化
	int sum = 0;			// 辺の重みの総和
	
	for(int i=0; i<m; i++){
		if(!same(E[i].u, E[i].v)){
			unite(E[i].u, E[i].v);
			sum += E[i].w;
		}
	}
	
	return sum;
}


int main()
{
	int n;
	cin >> n;
	
	int G[100][100];
	for(int i=0; i<n; i++){
		for(int j=0; j<n; j++){
			cin >> G[i][j];
		}
	}
	
	int m = 0;
	for(int i=0; i<n; i++){
		for(int j=i+1; j<n; j++){
			if(G[i][j]!=-1){
				E[m].u = i;
				E[m].v = j;
				E[m].w = G[i][j];
				m++;
			}
		}
	}
	
	cout << kruskal(m, n) << endl;
	
	return 0;
}
accuracy: 1
time_ms: 10
memory_kb: 3512
final_rank: 9