这是Kruskal算法的正确实现吗?

时间:2013-01-29 05:52:15

标签: c++ algorithm kruskals-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算法的实现是否正确?我做错了什么?

1 个答案:

答案 0 :(得分:0)

首先,为什么不使用union-find data structure而不是对指针结构进行复杂的操作?

其次,这个问题似乎有一个令人讨厌的伎俩。您不仅需要最小生成树。考虑案例

4
0.0 0.0
1.0 0.0
1.0 1.0
0.0 1.0

我只需要2平方(2)墨水即可连接所有点;我创建了两行长度为sqrt(2)的X。但是,最小生成树的长度为3。