簡體   English   中英

這是Kruskal算法的正確實現嗎?

[英]Is this a proper implementation of Kruskal's algorithm?

我編寫了以下代碼來解決UVA OnlineJudge問題#10034:

// problem 10034

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <iomanip>

using namespace std;

class tree;

class vertex {
public:
    double x,y;
    tree* mTree;
};

class tree {
public:
    tree(tree* last,vertex* v);

    int size();
    void assimilate(tree* other);

    tree* prev;
    tree* next;
    vector<vertex*> vertices;
};

tree::tree(tree* last,vertex* v) {
    prev = last;
    next = NULL;
    vertices.push_back(v);
    v->mTree = this;

    if(last != NULL) {
        last->next = this;
    }
}

int tree::size() {
    return vertices.size();
}

void tree::assimilate(tree* other) {
    int c;

    if(other->prev != NULL) {
    other->prev->next = other->next;
    }

    if(other->next != NULL) {
    other->next->prev = other->prev;
    }

    for(c = 0;c < other->vertices.size();c++) {
        this->vertices.push_back(other->vertices[c]);

        other->vertices[c]->mTree = this;
    }

    delete other;
}

class edge {
public:
    edge() {
        v1 = NULL;
        v2 = NULL;
        weight = 0;
    }

    edge(vertex* a,vertex* b,double w) {
        v1 = a;
        v2 = b;
        weight = w;
    }

    bool operator<(const edge& rhs) const {
        return this->weight < rhs.weight;
    }

    vertex* v1;
    vertex* v2;
    double weight;
};

double dist(double x1,double y1,double x2,double y2) {
    double dx;
    double dy;

    dx = x2 - x1;
    dy = y2 - y1;

    return sqrt((dx*dx) + (dy*dy));
}

int main() {
    int ncases;
    int ccase;
    int c;
    int nverts;
    int nedges;
    edge* edges;
    vertex* vertices;
    tree* lasttree;
    double cost;
    tree* t1;
    tree* t2;
    bool treeexists;
    int cedge;
    int cc;


    cin>>ncases;

    for(ccase = 0;ccase < ncases;ccase++) {
        cin>>nverts;
        nedges = (nverts*(nverts-1)) / 2;

        treeexists = false;
        lasttree = NULL;

        vertices = new vertex[nverts];
        edges = new edge[nedges];
        cedge = 0;

        for(c = 0;c < nverts;c++) {
            cin>>vertices[c].x;
            cin>>vertices[c].y;
            lasttree = new tree(lasttree,&vertices[c]);
        }

        for(c = 0;c < nverts;c++) {
            for(cc = c+1;cc < nverts;cc++) {
                edges[cedge] = edge(vertices+c,vertices+cc,dist(vertices[c].x,vertices[c].y,vertices[cc].x,vertices[cc].y));
                cedge++;
            }
        }

        sort(edges,edges+nedges);

        cost = 0;

        for(c = 0;c < nedges;c++) {
            //cout<<"edge with length "<<edges[c].weight<<endl;

            if(edges[c].v1->mTree != edges[c].v2->mTree) {
                //cout<<"using"<<endl;

                cost += edges[c].weight;

                t1 = edges[c].v1->mTree;
                t2 = edges[c].v2->mTree;

                if(t1->size() > t2->size()) {
                    t1->assimilate(t2);
                } else {
                    t2->assimilate(t1); 
                }
            }
        }

        if(ccase > 0) {
            cout<<endl;
        }

        cout<<fixed<<setprecision(2)<<cost;

        delete vertices[0].mTree;
        delete[] vertices;
        delete[] edges;
    }

    return 0;
}

它適用於問題附帶的測試用例以及我在這里找到的更大的測試用例: http : //online-judge.uva.es/board/viewtopic.php?p=21939#p21939

但是,當我將其提交給UVA時,會收到錯誤的答復消息。 我對Krukal算法的實現正確嗎? 我究竟做錯了什么?

首先,為什么不使用聯合查找數據結構而不是對指針結構進行復雜的操作?

第二,這個問題似乎有一個討厭的竅門。 您不只是想要最小的生成樹。 考慮一下情況

4
0.0 0.0
1.0 0.0
1.0 1.0
0.0 1.0

我只需要2 sqrt(2)單位墨水即可連接所有點; 我將兩行長度為sqrt(2)的X設為X。 但是,最小生成樹的長度為3。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM