Fix the minimum spanning tree algorithm.
Tinc uses Kruskal's algorithm to calculate a MST. However, this was broken in
commit 6e80da3370
. Revert back to the working
algorithm from tinc 1.0.
Thanks to Cheng LI for spotting the problem.
This commit is contained in:
parent
61275547cd
commit
1ddd6111a4
1 changed files with 22 additions and 5 deletions
27
src/graph.c
27
src/graph.c
|
@ -61,7 +61,7 @@
|
||||||
#include "graph.h"
|
#include "graph.h"
|
||||||
|
|
||||||
/* Implementation of Kruskal's algorithm.
|
/* Implementation of Kruskal's algorithm.
|
||||||
Running time: O(E)
|
Running time: O(EN)
|
||||||
Please note that sorting on weight is already done by add_edge().
|
Please note that sorting on weight is already done by add_edge().
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -78,11 +78,24 @@ static void mst_kruskal(void) {
|
||||||
for splay_each(node_t, n, node_tree)
|
for splay_each(node_t, n, node_tree)
|
||||||
n->status.visited = false;
|
n->status.visited = false;
|
||||||
|
|
||||||
/* Add safe edges */
|
/* Starting point */
|
||||||
|
|
||||||
for splay_each(edge_t, e, edge_weight_tree) {
|
for splay_each(edge_t, e, edge_weight_tree) {
|
||||||
if(!e->reverse || (e->from->status.visited && e->to->status.visited))
|
if(e->from->status.reachable) {
|
||||||
|
e->from->status.visited = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Add safe edges */
|
||||||
|
|
||||||
|
bool skipped = false;
|
||||||
|
|
||||||
|
for splay_each(edge_t, e, edge_weight_tree) {
|
||||||
|
if(!e->reverse || (e->from->status.visited == e->to->status.visited)) {
|
||||||
|
skipped = true;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
e->from->status.visited = true;
|
e->from->status.visited = true;
|
||||||
e->to->status.visited = true;
|
e->to->status.visited = true;
|
||||||
|
@ -93,8 +106,12 @@ static void mst_kruskal(void) {
|
||||||
if(e->reverse->connection)
|
if(e->reverse->connection)
|
||||||
e->reverse->connection->status.mst = true;
|
e->reverse->connection->status.mst = true;
|
||||||
|
|
||||||
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name,
|
logger(DEBUG_SCARY_THINGS, LOG_DEBUG, " Adding edge %s - %s weight %d", e->from->name, e->to->name, e->weight);
|
||||||
e->to->name, e->weight);
|
|
||||||
|
if(skipped) {
|
||||||
|
skipped = false;
|
||||||
|
next = edge_weight_tree->head;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue