시작 정점에서부터 출발하여 신장트리 집합을 단계적으로 확장해나가는 알고리즘이다.

쉽게 말하면 프림 알고리즘은 지금까지 연결된 정점에서 연결된 간선들 중 사이클을 만들지 않고 최소의 값을 갖는 간선을 하나씩 선택하면서 MST를 만들어가는 방식이다.

 

프림 알고리즘은 시작 정점을 정하고, 시작 정점에서 가까운 정점을 선택하면서 MST를 구성하므로 그 과정에서 사이클을 이루지 않는다. 그에 반해 크루스칼 알고리즘은 시작점을 정하지 않고, 최소 비용의 간선을 차례로 대입하면서 MST를 구성하므로, 그 과정에서 사이클을 이루는지 항상 확인해야 한다. 이 때, Union-Find(Disjoint-Set) 방법을 이용하여 사이클을 확인한다.

시간 복잡도

  • 프림 : O(V^2+E) → O(E logV)
  • 크루스칼 : O(E logE)

 

**프림은 정점 위주의 알고리즘, 크루스칼은 간선 위주의 알고리즘

**시간 복잡도는 비슷하지만, 보통 밀집한 그래프의 경우 프림이, 그렇지 않은 경우에는 크루스칼이 유리하다.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

import java.util.ArrayList;

import java.util.LinkedList;

import java.util.PriorityQueue;

import java.util.Queue;

import java.util.Scanner;

 

public class prim {

    

    static int V,E;

    static boolean visit[];

    static ArrayList<Edge>[] graph;

    static ArrayList<Edge> MST;

    

    public static void main(String[] args) {

        Scanner sc = new Scanner(System.in);

 

        V = sc.nextInt();

        E = sc.nextInt();

        

        graph = new ArrayList[V+1];

        visit = new boolean[V+1];

        

        for(int i=0; i<=V; i++

                graph[i] = new ArrayList<>();

        

        MST = new ArrayList<>();

        

        for(int i=1; i<=E; i++) {

                int u = sc.nextInt();

                int v = sc.nextInt();

                int val = sc.nextInt();

                

                graph[u].add(new Edge(u, v, val));

                graph[v].add(new Edge(v, u, val));

        }

        int point = 1;

        solve(point);

        

        for(int i=0; i<MST.size(); i++) {

                System.out.println(MST.get(i).begin + " " +MST.get(i).end+" "+MST.get(i).value);

        }

    }

    

    

    private static void solve(int P) {

        // TODO Auto-generated method stub

 

        PriorityQueue<Edge> pq = new PriorityQueue<>();

        Queue<Integer> queue = new LinkedList<>();        

        

        queue.add(P);

        

        while(!queue.isEmpty()) {

                int now = queue.poll();

                visit[now] = true;

                

                for(Edge e : graph[now]) {

                    if(!visit[e.end])

                        pq.add(e);

                }

                

                while(!pq.isEmpty()) {

                    Edge e = pq.poll();

                    if(!visit[e.end]) {

                        queue.add(e.end);

                        visit[e.end] = true;

                        MST.add(e);

                        break;

                    }

                }

        }

        

    }

 

 

    public static class Edge implements Comparable<Edge>{

        int begin;

        int end;

        int value;

        

        public Edge(int b, int e, int v) {

            this.begin = b;

            this.end = e;

            this.value = v;

        }

        

        

        @Override

        public int compareTo(Edge o) {

            // TODO Auto-generated method stub

            return this.value - o.value;

        }

        

    }

}

 

Colored by Color Scripter

cs

+ Recent posts