我编写了以下代码作为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算法的实现是否正确?我做错了什么?
答案 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。