版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lvxiangyu11/article/details/79771462
原理略过,第三版算导p368,以下代码可以用最小生成堆进行优化
#include<iostream>
#include<ctime>
#include<vector>
/*
This programme is realize bulid a gragh min tree by Kruskal Algotithm
Editor:Xiangyu Lv
email:[email protected]
frist-edit-time:2018年3月30日12:46:13
ALL RIGHTS RESERVED!
*/
#define DEBUG
using namespace std;
typedef int Vertex;
typedef int Weight;
class GraphListAndEdge {
public:
explicit GraphListAndEdge() {
edgeList.resize(0);
list.resize(0);
nameList.resize(0);
}
void insert(Vertex v0, Vertex v1, Weight w) {
int v0Loc = find(v0);
if (v0Loc == -1)
v0Loc = _new_node(v0);
int v1Loc = find(v1);
if (v1Loc == -1)
v1Loc = _new_node(v1);
EdgeNode * newEN = new EdgeNode;
newEN->Loc = v1Loc;
newEN->BratherNode = list[v0Loc].jointEdge;
newEN->weight = w;
newEN->vertex = v1;
list[v0Loc].jointEdge = newEN;
size_t i = 0;
for (; i < edgeList.size(); i++) {
if (edgeList[i].weight > w) {//升序排序
break;
}
}
EdgeListNode newELN;
newELN.v0Loc = v0Loc;
newELN.v1Loc = v1Loc;
newELN.weight = w;
if (edgeList.size()!=0)
edgeList.insert(edgeList.begin() + i , newELN);
else
edgeList.push_back(newELN);
}
void KruskalTinyStree() {
MINweight = 0;
disjointSet.resize(nameList.size(), -1);
know.resize(nameList.size(), false);
for (size_t i = 0; i < edgeList.size(); i++) {
//if (know[edgeList[i].v0Loc] == false || know[edgeList[i].v1Loc] == false) {
if (!_disjoint_if_joint(edgeList[i].v0Loc, edgeList[i].v1Loc)) {//不相交
_disjoint_union(edgeList[i].v0Loc, edgeList[i].v1Loc);
#ifdef DEBUG
cout << "连接:" << list[edgeList[i].v0Loc].vertex << " " << list[edgeList[i].v1Loc].vertex << endl;
#endif // DEBUG
know[edgeList[i].v0Loc] = true;
know[edgeList[i].v1Loc] = true;
MINweight += edgeList[i].weight;
}
//}
}
//检测不是连通图
for (size_t i = 0; i < list.size(); i++) {
if (know[i] == false)
cout << "存在不是连通图的一个点名称是:" <<list[i].vertex<< endl;
}
cout << "最小生成树的总权值是:" << MINweight << endl;
}
private:
struct EdgeNode
{
Vertex vertex;
int Loc;
Weight weight;
EdgeNode * BratherNode;
};
struct ListStack
{
Vertex vertex;
Weight weight;
EdgeNode * jointEdge;
};
struct EdgeListNode
{
Weight weight;
int v0Loc;
int v1Loc;
};
vector<ListStack> list;
vector<EdgeListNode> edgeList;
vector<Vertex> nameList;
vector<int> disjointSet;//用不相交集存每个树的集合
vector<bool> know;
int MINweight;
int find(Vertex v0) {
for (size_t i = 0; i < nameList.size(); i++)
{
if (nameList[i] == v0)
return i;
}
return -1;
}
int _new_node(Vertex v0) {
ListStack newStack;
newStack.vertex = v0;
newStack.jointEdge = nullptr;
newStack.weight = 0;
list.push_back(newStack);
nameList.push_back(v0);
return nameList.size() - 1;
}
bool _disjoint_if_joint(int v0loc, int v1loc) {//在同一个集合内返回真,否则返回假
#ifdef DEBUG
cout << " 检测:" << v0loc << " " << v1loc << endl;
#endif // DEBUG
if (_disjoint_find(v0loc) == _disjoint_find(v1loc))
return true;
return false;
}
void _disjoint_union(int v0loc, int v1loc) {//用启发式修改
v0loc = _disjoint_find(v0loc);
v1loc = _disjoint_find(v1loc);
if (disjointSet[v0loc] < disjointSet[v1loc]) {//v0比v1深
disjointSet[v1loc] = v0loc;
disjointSet[v0loc]--;
}
else
if (disjointSet[v0loc] == disjointSet[v1loc]) {
disjointSet[v1loc] = v0loc;
disjointSet[v0loc]--;
}
else {
disjointSet[v0loc] = v1loc;
disjointSet[v1loc]--;
}
}
int _disjoint_find(int loc) {//不相交集收缩
if (disjointSet[loc] > -1)
return disjointSet[loc] = _disjoint_find(disjointSet[loc]);
else
return loc;
}
};
int main() {
GraphListAndEdge myGraph;
int i = 0;
cin >> i;
for (int j = 0; j < i; j++) {
Vertex v0, v1, w;
cin >> v0 >> v1 >> w;
myGraph.insert(v0, v1, w);
}
myGraph.KruskalTinyStree();
#ifdef DEBUG
system("pause");
#endif // DEBUG
return 0;
}
/*
28
1 2 4
2 1 4
1 8 8
8 1 8
2 8 11
8 2 11
2 3 8
3 2 8
3 9 2
9 3 2
9 8 7
8 9 7
8 7 1
7 8 1
9 7 6
7 9 6
7 6 2
6 7 2
3 6 4
6 3 4
3 4 7
4 3 7
4 6 14
6 4 14
4 5 9
5 4 9
5 6 10
6 5 10
Output:
检测:2 5
连接:8 7
检测:5 2
检测:3 4
连接:3 9
检测:4 3
检测:5 6
连接:7 6
检测:6 5
检测:0 1
连接:1 2
检测:1 0
检测:3 6
连接:3 6
检测:6 3
检测:4 5
检测:5 4
检测:4 2
检测:2 4
检测:3 7
连接:3 4
检测:7 3
检测:0 2
连接:1 8
检测:2 0
检测:1 3
检测:3 1
检测:7 8
连接:4 5
检测:8 7
检测:8 6
检测:6 8
检测:1 2
检测:2 1
检测:7 6
检测:6 7
最小生成树的总权值是:37
*/