用Kruskal算法计算最小生成树时答案错误



我正在尝试使用kruskal算法解决这个关于spoj的MST问题。我的程序似乎在所有的测试用例上都能工作,但是spoj在这个代码上反复给出WA。

我无法在此代码中找到任何失败的测试用例。谁能指出我做错了什么吗?

import java.io.PrintWriter;
import java.util.Arrays;

public class CSTREET {
    static final int MAX = 1002;
    static Node edgeList[];
    static int parent[] = new int[MAX];

    public static void main(String[] args) throws Exception {
        Reader in = new Reader();
        PrintWriter out = new PrintWriter(System.out, true);
        int t = in.nextInt();
        while (t-- != 0) {
            int price = in.nextInt();
            int vertices = in.nextInt();
            int edge = in.nextInt();
            int idx = 0;
            edgeList = new Node[edge];
            for (int i = 1; i <= vertices; i++) {
                parent[i] = i;
            }
            while (idx < edge) {
                int src = in.nextInt();
                int dest = in.nextInt();
                int cost = in.nextInt();
                Node node = new Node(src, dest, cost);
                edgeList[idx] = node;
                idx++;
            }
            Arrays.sort(edgeList);
            int edgeCount = 0;

            long totalCost = 0;
            idx = 0;
            while (edgeCount < vertices-1 ) {
                Node curEdge = edgeList[idx];
                if (!checkCycle(curEdge.src, curEdge.dest)) {
                    edgeCount++;
                    totalCost += curEdge.cost;
                }
                idx++;
            }
            out.println(totalCost * price);
        }
    }

    static boolean checkCycle(int src, int dest) {
        if (findParent(src) == findParent(dest)) {
            return true;
        }
        while (parent[dest] != parent[src]) {
            parent[dest] = src;
            src = parent[src];
        }
        return false;
    }
    static int findParent(int i) {
        while (parent[i] != i) {
            i = parent[i];
        }
        return i;
    }

    static class Node implements Comparable<Node> {
        int src;
        int dest;
        int cost;
        public Node(int src, int dest, int cost) {
            this.src = src;
            this.dest = dest;
            this.cost = cost;
        }
        @Override
        public int compareTo(Node o) {
            return this.cost - o.cost;
        }
    }
}

您的联合查找实现不正确。考虑以下示例

x -> y ( y is parent of x )
A -> B -> C
D -> E

当你调用checkCycle( A, D)时,应该发生的是所有的5个节点都应该到一个集合,例如:

A -> B -> C
D -> E -> C

但是在你的代码中发生的是:

A -> B -> C
D -> C
E

这显然是不正确的。

您可以按如下方式更改checkCycle:

static boolean checkCycle(int src, int dest) {
    int srcRoot = findParent(src);
    int destRoot = findParent(dest);
    if (srcRoot == destRoot ) {
        return true;
    }
    parent[destRoot] = srcRoot;
    return false;
}

我强烈建议您阅读维基百科关于Disjoint-set的文章,并实现路径压缩版本,这可以提高复杂性。

最新更新