ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [백준] 1197 최소 스패닝 트리
    ALGORITHM/BOJ 2020. 11. 7. 21:19

    www.acmicpc.net/problem/1197

     

    1197번: 최소 스패닝 트리

    첫째 줄에 정점의 개수 V(1 ≤ V ≤ 10,000)와 간선의 개수 E(1 ≤ E ≤ 100,000)가 주어진다. 다음 E개의 줄에는 각 간선에 대한 정보를 나타내는 세 정수 A, B, C가 주어진다. 이는 A번 정점과 B번 정점이

    www.acmicpc.net

    2020-11-07


    # 스패닝 트리 (Spanning Tree)모든 정점들을 최소 간선의 수로 연결한 트리. 

      - 모든 정점이 연결이 되어 있어야 함

      - 사이클을 포함해서는 안됨

      - n개의 정점을 n-1개의 간선으로 연결

     

    #최소 스패닝 트리(Minimum Spanning Tree)Spanning Tree에서 정점들을 연결한 간선들의 가중치 합이 최소인 트리.

      1) 크루스칼 (Kruskal) 알고리즘

         - 가중치가 가장 낮은 간선을 선택하고 정점들을 이어나감

         - 이 때, 사이클의 생성을 막기 위해 union-find를 사용함

      2) 프림(Prim) 알고리즘

         - 정점을 기준으로 함

     

     

    // 최소 스패닝 트리
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import java.util.StringTokenizer;
    
    class Graph implements Comparable<Graph> {
    	int start;
    	int end;
    	int weight;
    
    	Graph(int start, int end, int weight) {
    		this.start = start;
    		this.end = end;
    		this.weight = weight;
    	}
    
    	@Override
    	public int compareTo(Graph o) {
    		return this.weight - o.weight;
    	}
    }
    
    public class Main1197 {
    	public static int V, E, parent[], result;
    	public static List<Graph> list;
    
    	public static void union(int x, int y) {
    		x = find(x);
    		y = find(y);
    
    		if (x != y) {
    			parent[y] = x;
    		}
    	}
    
    	public static int find(int x) {
    		if(parent[x] == x) return x;
    		return parent[x] = find(parent[x]);
    	}
    
    	public static void main(String[] args) throws Exception {
    		BufferedReader bf = new BufferedReader(new InputStreamReader(System.in));
    		StringTokenizer st = new StringTokenizer(bf.readLine());
    		V = Integer.parseInt(st.nextToken());
    		E = Integer.parseInt(st.nextToken());
    		list = new ArrayList<Graph>();
    		parent = new int[V+1];
    		result = 0;
    		for(int i = 1; i <= V; i++) parent[i] = i;
    		
    		for (int i = 0; i < E; i++) {
    			st = new StringTokenizer(bf.readLine());
    			int start = Integer.parseInt(st.nextToken());
    			int end = Integer.parseInt(st.nextToken());
    			int weight = Integer.parseInt(st.nextToken());
    			list.add(new Graph(start, end, weight));
    		}
    
    		Collections.sort(list);
    
    		for(int i = 0; i < list.size(); i++) {
    			int start = list.get(i).start;
    			int end = list.get(i).end;
    			if(find(start) != find(end)) {
    				union(start, end);
    				result += list.get(i).weight;
    			}
    		}
    		
    		System.out.println(result);
    	}
    }

     

    크루스칼 알고리즘으로 풀었다.

     

    1. parent 객체를 초기화 한다.

     

    2. 가중치를 기준으로 오름차순 정렬을 한다.

     

    3. 정렬한 가중치를 기준으로, 가중치가 작은 간선부터 체크한다.

     3-1) union-find를 이용하여 정점이 연결되어 있다면, union을 해주고 가중치를 더해준다.

     3-2) 이미 연결되어 있다면, 가중치를 더하지 않는다.

     

    	@Override
    	public int compareTo(Graph o) {
    		return this.weight - o.weight;
    	}

    처음 제출 했을 때 compareTo 메서드에서 작을 때, 같을 때, 클 때 3가지 케이스를 모두 커버 못해서 틀렸었다. 

     

    'ALGORITHM > BOJ' 카테고리의 다른 글

    [백준] 2644 촌수계산  (0) 2020.11.09
    [백준] 1068 트리  (0) 2020.11.08
    [백준] 1149 RGB거리  (0) 2020.11.07
    [백준] 2606 바이러스  (0) 2020.11.06
    [백준] 13300 방 배정  (0) 2020.11.06

    댓글

Programming Diary