#java #algorithm #minimum-spanning-tree #kruskals-algorithm #union-find
#java #алгоритм #минимальное связующее дерево #крускалс-алгоритм #объединение-найти
Вопрос:
Я пытаюсь решить этот MST-вопрос по spoj, используя алгоритм Крускала. моя программа, похоже, работает во всех тестовых примерах, но 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;
}
}
}
Комментарии:
1. Пожалуйста, укажите код, который вы фактически отправляете. Я получаю ошибку компиляции при отправке этого кода.
Ответ №1:
Ваша реализация union-find неверна. Рассмотрим этот пример
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 и реализовать версию сжатия пути, что повышает сложность.
Комментарии:
1. Спасибо. это действительно была ошибка в моей реализации union-find.