https://www.acmicpc.net/problem/1368
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.PriorityQueue;
import java.util.StringTokenizer;
public class Main {
static int N;
static int[] wellCosts, parents;
static PriorityQueue<Edge> edges;
static void input() {
Reader scanner = new Reader();
N = scanner.nextInt();
edges = new PriorityQueue<>();
wellCosts = new int[N + 1];
parents = new int[N + 1];
for(int idx = 1; idx <= N; idx++) {
int makeCost = scanner.nextInt();
wellCosts[idx] = makeCost;
parents[idx] = idx;
}
for(int start = 1; start <= N; start++) {
for(int end = 1; end <= N; end++) {
int cost = scanner.nextInt();
if(start == end) edges.add(new Edge(0, start, wellCosts[start]));
else edges.add(new Edge(start, end, cost));
}
}
}
static void solution() {
System.out.println(kruskal());
}
static int kruskal() {
int count = 0, totalCost = 0;
while(count < N) {
Edge cur = edges.poll();
int start = cur.start, end = cur.end, cost = cur.cost;
if(!isSameParent(start, end)) {
union(start, end);
count++;
totalCost += cost;
}
}
return totalCost;
}
static int findParent(int ricePaddy) {
if(ricePaddy == parents[ricePaddy]) return ricePaddy;
return parents[ricePaddy] = findParent(parents[ricePaddy]);
}
static void union(int ricePaddy1, int ricePaddy2) {
int parent1 = findParent(ricePaddy1), parent2 = findParent(ricePaddy2);
if(parent1 != parent2) {
if(parent1 < parent2) parents[parent2] = parent1;
else parents[parent1] = parent2;
}
}
static boolean isSameParent(int ricePaddy1, int ricePaddy2) {
int parent1 = findParent(ricePaddy1), parent2 = findParent(ricePaddy2);
return parent1 == parent2;
}
static class Edge implements Comparable<Edge> {
int start, end, cost;
public Edge(int start, int end, int cost) {
this.start = start;
this.end = end;
this.cost = cost;
}
@Override
public int compareTo(Edge e) {
return cost - e.cost;
}
}
public static void main(String[] args) {
input();
solution();
}
static class Reader {
BufferedReader br;
StringTokenizer st;
public Reader() {
br = new BufferedReader(new InputStreamReader(System.in));
}
String next() {
while(st == null || !st.hasMoreElements()) {
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
int nextInt() {
return Integer.parseInt(next());
}
}
}