프림 알고리즘

    public static boolean connected [];
    public static ArrayList<ArrayList<Edge>> nodes;

    static class Edge implements Comparable<Edge> {
        int from, to;
        double length;

        public Edge(int from, int to, double length) {
            super();
            this.from = from;
            this.to = to;
            this.length = length;
        }
        @Override
        public int compareTo(Edge other) {
            return Double.compare(this.length, other.length);
        }
    }

    public static double getPrimsMinSum() {
        double sum = 0;
        // get start point's candidate edges, start is 0 node
        ArrayList<Edge> edges = nodes.get(0);
        PriorityQueue<Edge> pq = new PriorityQueue<Edge>();
        pq.addAll(edges);

        // prims
        while (!pq.isEmpty()) {
            Edge edge = pq.poll();

            // if already from, to connected then bypass
            if (connected[edge.from] && connected[edge.to]) {
                continue;
            }

            // edge connect
            connected[edge.from] = true;
            connected[edge.to] = true;
            sum += edge.length;

            // next candidate edges
            ArrayList<Edge> nextEdges = nodes.get(edge.to); // edge.to is new 'from'
            pq.addAll(nextEdges);
        }
        return sum;
    }

쿠르스칼 알고리즘

    // 쿠르스칼에서는, circle을 판단하기위한 부분이 필요하다.
    public static int root[] = new int[TotalNodeNumber];

    public static void initRoot() {
        // 처음에는 모든 node의 부모는 자기 자신이니깐 -1로 설정
        Arrays.fill(root, -1);
    }

    public static int find(int index) {
        // 0보다 작으면 최상위 부모임.
        if (roots[index] < 0) {
            return index;
        }

        // 아니면 부모의 indxe을 가지고 있으니깐 찾아라~
        return find(roots[index]);
    }

    // 서로 다른 두개의 그룹을 합치는 방법.
    // 두 그룹의 최상위 부모를 알아온뒤, 한쪽 최상위 부모를 다른쪽 부모에다가 달면 됨.
    public static void union(int a, int b) {
        int root1 = find(a);
        int root2 = find(b);

        // 이미 같은 그룹이라면
        if (root1 == root2) {
            return;
        }

        // root1과 root2를 결합하고, root2의 부모를 roo1로 설정
        roots[root1] += roots[root2];
        roots[root2] = root1;

    }

    public static ArrayList<Edge> edges;
    public static double getKrusKalMinSum() {
        double sum = 0;
        int edgeCount = 0;

        // 가능한 모든 edges을 queue에 넣는다. queue을 쓰지 않는 경우, sort을 이용해도 무관하다.
        PriorityQueue<Edge> pq = new PriorityQueue<Edge>();
        pq.addAll(edges);

        while(!pq.isEmpty()) {
            // 길이가 가장 짧은 (최적의) edge을 가져온다.
            Edge edge = pq.poll();

            int aRootIndex = find(edge.from);
            int bRootIndex= find(edge.to);

            // 시작점, 도착점의 최상위 부모를 가져온다.                 
            if (aRootIndex == bRootIndex) {
                // 만약 최상위 부모가 같으면, 현재 이미 연결선이 있는 상태에서 circle이 발생하는 것이다.
                // 따라서 최상위 부모가 같으면 패스..
                continue;
            } else {
                sum += edge.length;
                ++edgeCount; // edge 카운팅을 하는 이유는, N-1개의 선이 연결되면 트리가 완성! 이걸 체크하기위해서.

                if (edgeCount + 1 == N) {
                    break;
                }

                // edge가 연결되었으니, edge연결을 관리(circle판단)하는 root배열을 갱신!
                union(aRootIndex, bRootIndex);
            }
        }
    }

results matching ""

    No results matching ""