-
Notifications
You must be signed in to change notification settings - Fork 0
/
MST.cpp
114 lines (94 loc) · 3.63 KB
/
MST.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
//
// Created by Mark Jan Kamminga on 06-02-16.
//
#include <algorithm>
#include "Mst.h"
int Mst::find(Room* t) {
if (typeLevels.find(t) != typeLevels.end()) {
return typeLevels[t];
}
return -1;
}
void Mst::addEdge(Room *from, Room *to, int distance) {
pq.push_back(make_pair(distance, make_pair(from, to)));
}
bool Mst::calc() {
if (!calculated) {
//Sort the rooms from smallest to biggest
sort(pq.begin(), pq.end());
int num = 1;
while (!pq.empty()) {
int distance = pq.begin()->first;
Room *from = pq.begin()->second.first;
Room *to = pq.begin()->second.second;
int fromLevel = find(from);
int toLevel = find(to);
pq.erase(pq.begin());
if (num < size && ((toLevel == -1 && fromLevel == -1) || fromLevel != toLevel)) {
if (toLevel == -1 && fromLevel == -1) {
levels[++currentLevel] = vector<Room *>();
levels[currentLevel].push_back(to);
levels[currentLevel].push_back(from);
typeLevels[to] = currentLevel;
typeLevels[from] = currentLevel;
} else if (toLevel == -1 && fromLevel >= 0) {
typeLevels[to] = fromLevel;
levels[fromLevel].push_back(to);
} else if (fromLevel == -1 && toLevel >= 0) {
typeLevels[from] = toLevel;
levels[toLevel].push_back(from);
} else if (fromLevel >= 0 && toLevel >= 0) {
int copyFrom;
int moveTo;
if (fromLevel > toLevel) {
copyFrom = fromLevel;
moveTo = toLevel;
} else {
copyFrom = toLevel;
moveTo = fromLevel;
}
for (auto it = levels[copyFrom].begin(); it != levels[copyFrom].end(); it++) {
typeLevels[it.operator*()] = moveTo;
//levels[moveTo].push_back(it.operator*());
}
levels[moveTo].insert(levels[moveTo].end(), levels[copyFrom].begin(), levels[copyFrom].end());
levels.erase(levels.find(copyFrom));
} else {
return false;
}
minimalSpanningTreePaths[make_pair(to, from)] = distance;
minimalSpanningTreePaths[make_pair(from, to)] = distance;
num++;
} else {
excludedSanningTreePaths[make_pair(to, from)] = distance;
}
}
calculated = true;
}
return true;
}
bool Mst::isCalculated() {
return calculated;
}
bool Mst::isInSpanningTree(Room *from, Room *to) {
return minimalSpanningTreePaths.find(make_pair(from, to)) != minimalSpanningTreePaths.end();
}
bool Mst::collapse(int num) {
if (num <= excludedSanningTreePaths.size()) {
int totalNum = num - 1;
Room *from = nullptr;
Room *to = nullptr;
for (auto it = excludedSanningTreePaths.begin(); it != excludedSanningTreePaths.end() && num > 0; it++, num--) {
from = it.operator*().first.first;
to = it.operator*().first.second;
from->removeEdge(to);
to->removeEdge(from);
}
auto end = excludedSanningTreePaths.find(make_pair(from, to));
if (end != excludedSanningTreePaths.end()) {
excludedSanningTreePaths.erase(excludedSanningTreePaths.begin(), end);
}
return true;
}
return false;
}