문제
그래프가 주어졌을 때, 그 그래프의 최소 스패닝 트리를 구하는 프로그램을 작성하시오.
최소 스패닝 트리는, 주어진 그래프의 모든 정점들을 연결하는 부분 그래프 중에서 그 가중치의 합이 최소인 트리를 말한다.
입력
첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 정점과 B번 정점이 가중치 C인 간선으로 연결되어 있다는 의미이다. C는 음수일 수도 있으며, 절댓값이 1,000,000을 넘지 않는다.
그래프의 정점은 1번부터 V번까지 번호가 매겨져 있고, 임의의 두 정점 사이에 경로가 있다. 최소 스패닝 트리의 가중치가 -2,147,483,648보다 크거나 같고, 2,147,483,647보다 작거나 같은 데이터만 입력으로 주어진다.
출력
첫째 줄에 최소 스패닝 트리의 가중치를 출력한다.
테스트 케이스
입력 1
3 3
1 2 1
2 3 2
1 2 -100
출력 1
-98
입력 2
3 3
1 2 1
2 3 2
1 3 3
출력 2
3
입력 3
3 3
1 2 -50
1 3 -40
2 3 50
출력 3
-90
접근
MST문제이므로, 크루스칼 알고리즘이나, 프림 알고리즘 둘 중하나 선택해서 문제가 해결됩니다
저는 프림 알고리즘을 이용하여서 풀이하였습니다.
처음에 인접행렬을 이용하여 프림 알고리즘을 구현 하였더니 메모리초과가 발생했습니다.
최대 정점을 10000개 만들 수 있으니, 2차원 배열을 사용하니 시작하자마자 메모리가 초과됐습니다.
그래서 인접리스트로 구현하였습니다.
코드
import java.io.*;
import java.util.*;
class Vertex{
int end;
int weight;
public Vertex(int end,int weight) {
this.end = end;
this.weight = weight;
}
}
public class Main {
static int V,E;
public static void main(String[] args) throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(System.out));
StringTokenizer st = new StringTokenizer(br.readLine());
V = Integer.parseInt(st.nextToken());
E = Integer.parseInt(st.nextToken());
boolean visit[] = new boolean[V];
//int matrix[][] = new int[V][V];
ArrayList<Vertex>[] list = new ArrayList[V];
for(int i=0; i<V; i++) {
list[i] = new ArrayList<>();
}
int minEdge[] = new int[V];
for(int i=0; i<E; i++) {
st = new StringTokenizer(br.readLine());
//matrix[Integer.parseInt(st.nextToken())-1][Integer.parseInt(st.nextToken())-1] = Integer.parseInt(st.nextToken());
int v1 = Integer.parseInt(st.nextToken());
int v2 = Integer.parseInt(st.nextToken());
int w = Integer.parseInt(st.nextToken());
list[v1-1].add(new Vertex(v2-1,w));
list[v2-1].add(new Vertex(v1-1,w));
}
Arrays.fill(minEdge, (int)10e9);
minEdge[0] = 0;
int result = 0;
for(int c=0; c<V; c++) {
int min = (int)10e9;
int minVertex = 0;
for(int i=0; i<V; i++) {
if(!visit[i] && min > minEdge[i]) {
min = minEdge[i];
minVertex = i;
}
}
visit[minVertex] = true;
result += min;
// for(int i=0; i<V; i++) {
// if(!visit[i] && minEdge[i] > list[minVertex].get(i) && list[minVertex].get(i) !=0) {
// minEdge[i] = list[minVertex].get(i);
// }
// }
for(int i=0; i<list[minVertex].size(); i++) {
int temp = list[minVertex].get(i).end;
if(!visit[temp] && list[minVertex].get(i).weight< minEdge[temp]) {
minEdge[temp] = list[minVertex].get(i).weight;
}
}
}
bw.write(String.valueOf(result));
br.close();
bw.flush();
bw.close();
}
}
주의
2차원배열 멈춰~!
'공부 정리 > 백준' 카테고리의 다른 글
[백준] 자바 17219 비밀번호 찾기 (0) | 2022.03.23 |
---|---|
[백준] 자바 1717 집합의 표현 (0) | 2022.03.23 |
[백준] 자바 11659 구간 합 구하기4 (0) | 2022.03.15 |
[백준] 자바 2630 색종이 만들기 (0) | 2022.03.14 |
[백준] 자바 1074 Z (0) | 2022.03.04 |
댓글