Queue 가 아닌, Deque 을 활용
가중치가 0 이면 앞에 삽입, 1 이면 뒤에 삽입
for all v in verticces:
dist[v] = inf
dist[start] <- 0
deque d
d.push_front(start)
while d.empty() == false:
vertex = get front element and pop as in BFS
for all edges e of form(vertex, u):
if travelling e relaxes distance to u:
relax dist[u]
if e.weight = 1:
d.push_back(u)
else:
d.push_front(u)
시간 복잡도
우선 스패닝 트리가 무엇일까?

최소 + 스패닝 트리 ➡️ 스패닝 트리 中 가장 작은 것
의미는 쉬운데 막상 코드 작성 시 어려움…
작성 방식은 크게 두 가지 ⇒ **KRUSKAL / PRIM
왜 완전탐색은 안될까?
- 최소 신장 트리를 완전 탐색으로 생각
- 정점 30개, 간선 60개라 생각할 때 완전 탐색해서 MST 찾아보면?
- ⇒ 터쳐버림
💡
[중요 정보]
- 구현 : 정렬 + 그리디 + 유니온 파인드
- 시간 복잡도 :
- 간선이 적은 희소 그래프 에서 효율적



import java.util.*;
class Edge implements Comparable<Edge> {
int src, dest, weight;
public Edge(int src, int dest, int weight) {
this.src = src;
this.dest = dest;
this.weight = weight;
}
@Override
public int compareTo(Edge other) {
return this.weight - other.weight; // 가중치 오름차순 정렬
}
}
public class KruskalMST {
static int[] parent;
// 유니온-파인드: Find 연산
public static int find(int node) {
if (parent[node] == node) return node;
return parent[node] = find(parent[node]); // 경로 압축
}
// 유니온-파인드: Union 연산
public static void union(int node1, int node2) {
int root1 = find(node1);
int root2 = find(node2);
if (root1 != root2) {
parent[root2] = root1; // 두 집합을 합침
}
}
public static void main(String[] args) {
int vertices = 5; // 정점 개수
int edgesCount = 7; // 간선 개수
// 간선 리스트 초기화
List<Edge> edges = new ArrayList<>();
edges.add(new Edge(0, 1, 1)); // A-B: 1
edges.add(new Edge(0, 2, 3)); // A-C: 3
edges.add(new Edge(1, 2, 3)); // B-C: 3
edges.add(new Edge(1, 3, 6)); // B-D: 6
edges.add(new Edge(2, 3, 4)); // C-D: 4
edges.add(new Edge(2, 4, 2)); // C-E: 2
edges.add(new Edge(3, 4, 5)); // D-E: 5
// 유니온-파인드 초기화
parent = new int[vertices];
for (int i = 0; i < vertices; i++) {
parent[i] = i; // 초기에는 각 정점이 자신이 부모
}
// 간선 가중치 기준 정렬
Collections.sort(edges);
// 크루스칼 알고리즘 수행
List<Edge> mst = new ArrayList<>();
int mstWeight = 0;
for (Edge edge : edges) {
// 사이클이 생기지 않으면 간선 선택
if (find(edge.src) != find(edge.dest)) {
union(edge.src, edge.dest);
mst.add(edge);
mstWeight += edge.weight;
}
}
// 결과 출력
System.out.println("Minimum Spanning Tree:");
for (Edge edge : mst) {
System.out.printf("Edge: %d-%d, Weight: %d\n", edge.src, edge.dest, edge.weight);
}
System.out.println("Total Weight: " + mstWeight);
}
}
Minimum Spanning Tree:
Edge: 0-1, Weight: 1
Edge: 2-4, Weight: 2
Edge: 0-2, Weight: 3
Edge: 2-3, Weight: 4
Total Weight: 10
💡
[중요 정보]
- 구현 : 그리디 + 우선순위 큐
- 시간 복잡도 :
- 간선이 많은 밀집 그래프 에서 효율적


import java.util.*;
class PrimMST {
static class Edge implements Comparable<Edge> {
int dest, weight;
public Edge(int dest, int weight) {
this.dest = dest;
this.weight = weight;
}
@Override
public int compareTo(Edge other) {
return this.weight - other.weight; // 가중치 기준 오름차순 정렬
}
}
public static void main(String[] args) {
int vertices = 5; // 정점의 개수
// 그래프를 인접 리스트로 초기화
List<List<Edge>> graph = new ArrayList<>();
for (int i = 0; i < vertices; i++) {
graph.add(new ArrayList<>());
}
// 간선 추가 (무방향 그래프)
graph.get(0).add(new Edge(1, 1)); // A-B: 1
graph.get(1).add(new Edge(0, 1));
graph.get(0).add(new Edge(2, 3)); // A-C: 3
graph.get(2).add(new Edge(0, 3));
graph.get(1).add(new Edge(2, 3)); // B-C: 3
graph.get(2).add(new Edge(1, 3));
graph.get(1).add(new Edge(3, 6)); // B-D: 6
graph.get(3).add(new Edge(1, 6));
graph.get(2).add(new Edge(3, 4)); // C-D: 4
graph.get(3).add(new Edge(2, 4));
graph.get(2).add(new Edge(4, 2)); // C-E: 2
graph.get(4).add(new Edge(2, 2));
graph.get(3).add(new Edge(4, 5)); // D-E: 5
graph.get(4).add(new Edge(3, 5));
// 우선순위 큐를 사용하여 최소 가중치 간선을 선택
PriorityQueue<Edge> pq = new PriorityQueue<>();
boolean[] visited = new boolean[vertices]; // 방문 여부 체크
int mstWeight = 0; // MST 가중치 합
List<String> mstEdges = new ArrayList<>(); // MST 간선 리스트
// 시작 정점 (0번 정점)
pq.add(new Edge(0, 0));
while (!pq.isEmpty()) {
Edge current = pq.poll(); // 가장 가중치가 작은 간선 선택
if (visited[current.dest]) continue; // 이미 방문한 정점이면 스킵
visited[current.dest] = true; // 정점 방문 처리
mstWeight += current.weight; // MST 가중치 추가
// 간선을 기록 (시작 정점이 있는 경우 출력)
if (current.weight != 0) {
mstEdges.add(String.format("Edge: %d, Weight: %d", current.dest, current.weight));
}
// 현재 정점에 연결된 간선을 큐에 추가
for (Edge neighbor : graph.get(current.dest)) {
if (!visited[neighbor.dest]) {
pq.add(neighbor);
}
}
}
// 결과 출력
System.out.println("Minimum Spanning Tree:");
for (String edge : mstEdges) {
System.out.println(edge);
}
System.out.println("Total Weight: " + mstWeight);
}
}
| 가중치 조건 | 알고리즘 | 시간 복잡도 | 설명 |
|---|---|---|---|
| 가중치 없음 | BFS | O(V+E) | 가중치가 없는 무향 또는 유향 그래프에서 최단 경로를 구함. |
| 가중치 0과 1 | 0/1 BFS | O(V+E) | 간선의 가중치가 0 또는 1로 한정될 때 효율적. |
| 가중치 양수 | 다익스트라 | O((V+E)logV) | 우선순위 큐를 활용하여 양수 가중치의 최단 경로를 효율적으로 계산. |
| 가중치 음수 포함 | 벨만포드 | O(VE) | 음수 가중치가 있는 그래프에서도 안전하게 최단 경로 계산 가능. |
| 모든 정점 간 최단 경로 | 플로이드-워셜 | O(V^3) | 그래프의 모든 정점 쌍 사이의 최단 경로를 구함. |
| MST, 모든 정점 방문 시 최소 가중치, 간선이 적은 희소 그래프 | 크루스칼 | O(ElogE) | 그리디 + 정렬 + 유니온 파인드 |
| MST, 모든 정점 방문 시 최소 가중치, 간선이 많은 밀집 그래프 | 프림 | O(ElogV) | 그리디 + 우선순위큐 |