크루스칼 알고리즘

 

  • 최소신장트리(MST)를 찾는 가장 대표적 방법이다
  • 그래프의 모든 정점을 연결할 때, 가장 적은 비용으로 연결할 때 사용하는 알고리즘
  • makeSet, findSet, union 메서드가 사용됨

 

 

 

 

동작 원리

1. 모든 간선을 가중치에따라 오름차순 정렬함

 

2. 가중치가 낮은 간선부터 선택하여 사이클이 형성되지 않을 경우 간선을 최종 채택

 

3. 간선을 추가할 땐 상호 배타 집합(Union-find)자료구조를 사용해 사이클 확인하고,
    같은 집합이 아니면 합집합으로 간선 연결 처리.

 

4. 같은 방법으로 모든 정점이 연결될 때까지 반복

 

 

 

활용 사례

1. 네트워크 설계 : 인터넷, 전기 등의 연결망 구성 시 연결 비용을 최소화하는 문제에 사용

 

2. 도로망 설계 : 여러 도시를 연결하는 도로망을 설계할 때 최소 비용으로 도시를 연결하기 위해 사용

 

 

장점

  • 간선을 선택해나가는 방식으로 구현이 간단한 편이다.

  • 간선을 정렬하는 방식이기 때문에, 간선의 수가 적은 경우에 유리하다.

 

단점

  • 간선을 정렬해야 한다는 점이 시간복잡도를 증가시킬 수 있음

  • 간선이 많을 때 비효율적일 수 있음

 

 

 

구현

import java.util.Arrays;
import java.util.Comparator;
import java.util.Scanner;

public class Kruskal {
	// 간선들을 객체화하여 배열로 관리하기 위한 간선 클래스 정의
	static class Edge implements Comparable<Edge> {
		int A, B, W;

		public Edge(int a, int b, int w) {
			super();
			A = a;
			B = b;
			W = w;
		}
		// 가중치를 기준으로 오름차순
		@Override
		public int compareTo(Edge o) {
			return this.W - o.W;
		}
	}

	static int[] p; // 대표자를 저장할 배열

	public static void main(String[] args) {
		Scanner sc = new Scanner(System.in);

		int V = sc.nextInt(); // 정점의 개수(정점의 시작번호를 보고)
		int E = sc.nextInt(); // 간선의 개수

		Edge[] edges = new Edge[E];

		for (int i = 0; i < E; i++) {
			int A = sc.nextInt();
			int B= sc.nextInt();
			int W = sc.nextInt();
			edges[i] =new Edge(A,B,W);

			edges[i] = new Edge(sc.nextInt(), sc.nextInt(), sc.nextInt());
		} // 입력 끝

		// 간선을 오름차순 정렬
		Arrays.sort(edges);

		// 상호배타집합 (서로소집합, 유니온파인드)
		p = new int[V];

		// 자기 자신을 부모로 만들어 부모노드를 저장하는 배열에 저장
		for (int i = 0; i < V; i++) {
			p[i] = i;
		}
		
		int ans = 0; // 최소비용을 저장하기 위한 변수
		int pick = 0; // 채택한 간선의 개수

		for (int i = 0; i < E; i++) {
			// 사이클 확인
			int px = findSet(edges[i].A);
			int py = findSet(edges[i].B);
			// 부모 노드가 서로 다르면 다른 집합이므로 간선 선택
			if (px != py) {
				union(px, py);
				ans += edges[i].W;
				pick++;
			}

			if (pick == (V - 1))
				break;

		}

		System.out.println(ans);

	}// main

	static int findSet(int x) {
		// 경로 압축 방식
		if (x != p[x])
			p[x] = findSet(p[x]);
		return p[x];
	}

	static void union(int x, int y) {
		p[y] = x;
	}
}