본문 바로가기
공부 정리/백준

[백준] 자바 1197 최소 스패닝 트리

by 경적필패. 2022. 3. 21.
반응형

문제

그래프가 주어졌을 때, 그 그래프의 최소 스패닝 트리를 구하는 프로그램을 작성하시오.

최소 스패닝 트리는, 주어진 그래프의 모든 정점들을 연결하는 부분 그래프 중에서 그 가중치의 합이 최소인 트리를 말한다.

입력

첫째 줄에 정점의 개수 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차원배열 멈춰~!

반응형

댓글