#include "init.hpp" inline void steiner_3(const vector> &adjList, vector &min_distance0, vector &origin0, Vertex v0, Vertex v1, Vertex v2) { vector min_distance1(adjList.size(), MAX_WEIGHT); vector origin1(adjList.size(), -1); vector min_distance2(adjList.size(), MAX_WEIGHT); vector origin2(adjList.size(), -1); dijkstra(adjList, min_distance1, origin1, v1, v0, v2); if (min_distance0[v2] == min_distance1[v2]) { dijkstra(adjList, min_distance2, origin2, v2, v0, v1); } else { if (min_distance0[v2] < min_distance1[v2]) { dijkstra(adjList, min_distance2, origin2, v2, v0); } else { dijkstra(adjList, min_distance2, origin2, v2, v1); } } Vertex intersect = -1; Weight distIntersect = MAX_WEIGHT; for (unsigned int i = 0; i < adjList.size(); ++i) { if (min_distance2[i] != MAX_WEIGHT && min_distance1[i] != MAX_WEIGHT && min_distance0[i] != MAX_WEIGHT && min_distance0[i] + min_distance1[i] + min_distance2[i] < distIntersect) { intersect = i; distIntersect = min_distance0[i] + min_distance1[i] + min_distance2[i]; } } // Fill seen vector seen(adjList.size(), false); Vertex current = intersect; while (origin0[current] != -1) { seen[current] = true; current = origin0[current]; } seen[current] = true; // Merge origin1 into origin0 current = intersect; while (origin1[current] != -1) { if (!seen[origin1[current]]) { origin0[origin1[current]] = current; } seen[current] = true; current = origin1[current]; } seen[current] = true; // Merge origin2 into origin0 current = intersect; while (origin2[current] != -1) { if (!seen[origin2[current]]) { origin0[origin2[current]] = current; } current = origin2[current]; } } Tree incrementalDijks3(const Graph &G, Vertex root, const vector &terminalsMap, const vector &terminals) { vector> adjList = G.adjList; vector min_distance(G.adjList.size(), MAX_WEIGHT); vector origin(G.adjList.size(), -1); Vertex far = dijkstra(adjList, min_distance, origin, root, terminalsMap, terminals.size()); Weight far_dist = min_distance[far]; Vertex last_far = far; bool dijk_simple = true; while (far_dist > 0 && !tle) { if (dijk_simple) { dijk_simple = false; vector copy_distance = min_distance; vector copy_origin = origin; // Update graph, set edge to 0 last_far = far; Vertex current = far; while (origin[current] != -1 && copy_distance[current] != 0) { copy_distance[current] = 0; current = origin[current]; } current = far; set> active_vertices; while (origin[current] != -1 && min_distance[current] != 0) { for (map::const_iterator it = adjList[current].begin(); it != adjList[current].end(); ++it) { if (it->first != copy_origin[current] && copy_distance[it->first] > it->second) { active_vertices.erase({copy_distance[it->first], it->first}); active_vertices.insert({it->second, it->first}); copy_distance[it->first] = it->second; copy_origin[it->first] = current; } } current = origin[current]; } dijkstra(adjList, copy_distance, copy_origin, active_vertices); far_dist = 0; for (vector::const_iterator it = terminals.begin(); it != terminals.end(); ++it) { if (far_dist < copy_distance[*it]) { far_dist = copy_distance[*it]; far = *it; } } } else { dijk_simple = true; steiner_3(adjList, min_distance, origin, root, far, last_far); // Update graph Vertex current = far; while (origin[current] != -1) { adjList[current][origin[current]] = 0; adjList[origin[current]][current] = 0; min_distance[current] = MAX_WEIGHT; current = origin[current]; } current = last_far; while (origin[current] != -1) { adjList[current][origin[current]] = 0; adjList[origin[current]][current] = 0; min_distance[current] = MAX_WEIGHT; current = origin[current]; } dijkstra(adjList, min_distance, origin, root); far_dist = 0; for (vector::const_iterator it = terminals.begin(); it != terminals.end(); ++it) { if (far_dist < min_distance[*it]) { far_dist = min_distance[*it]; far = *it; } } } } // Build tree Tree T(G, root); for (unsigned int i = 0; i < G.adjList.size(); ++i) { if (origin[i] != -1) { T.tree[i].parent = origin[i]; T.tree[i].weight = G.adjList[i].find(origin[i])->second; T.tree[origin[i]].children.insert(i); } } return T; } Tree incrementalOptDijks3(const Graph &G, Vertex root, const vector &terminalsMap, const vector &terminals) { vector> adjList = G.adjList; vector min_distance(G.adjList.size(), MAX_WEIGHT); vector origin(G.adjList.size(), -1); Vertex far = dijkstra(adjList, min_distance, origin, root, terminalsMap, terminals.size()); Weight far_dist = min_distance[far]; vector full_backup_distance = min_distance; vector full_backup_origin = origin; vector current_terminals; vector current_terminalsMap(terminalsMap.size(), -1); current_terminals.reserve(terminals.size()); Vertex last_far = far; while (far_dist > 0 && !tle) { bool dijk_simple = true; for (int i = 0; i < 4 && far_dist > 0 && !tle; ++i) { if (dijk_simple) { current_terminalsMap[far] = current_terminals.size(); current_terminals.push_back(far); dijk_simple = false; vector backup_distance = min_distance; vector backup_origin = origin; // Update graph, set edge to 0 last_far = far; Vertex current = far; while (origin[current] != -1 && min_distance[current] != 0) { backup_distance[current] = 0; current = origin[current]; } current = far; set> active_vertices; while (origin[current] != -1 && min_distance[current] != 0) { for (map::iterator it = adjList[current].begin(); it != adjList[current].end(); ++it) { if (backup_distance[it->first] > it->second) { active_vertices.erase({backup_distance[it->first], it->first}); active_vertices.insert({it->second, it->first}); backup_distance[it->first] = it->second; backup_origin[it->first] = current; } } current = origin[current]; } dijkstra(adjList, backup_distance, backup_origin, active_vertices); far_dist = 0; for (vector::const_iterator it = terminals.begin(); it != terminals.end(); ++it) { if (far_dist < backup_distance[*it]) { far_dist = backup_distance[*it]; far = *it; } } } else { dijk_simple = true; current_terminalsMap[far] = current_terminals.size(); current_terminals.push_back(far); steiner_3(adjList, min_distance, origin, root, far, last_far); // Update graph Vertex current = far; while (origin[current] != -1) { adjList[current][origin[current]] = 0; adjList[origin[current]][current] = 0; min_distance[current] = MAX_WEIGHT; current = origin[current]; } current = last_far; while (origin[current] != -1) { adjList[current][origin[current]] = 0; adjList[origin[current]][current] = 0; min_distance[current] = MAX_WEIGHT; current = origin[current]; } dijkstra(adjList, min_distance, origin, root); far_dist = 0; for (vector::const_iterator it = terminals.begin(); it != terminals.end(); ++it) { if (far_dist < min_distance[*it]) { far_dist = min_distance[*it]; far = *it; } } } } Tree T(G, root); for (unsigned int i = 0; i < G.adjList.size(); ++i) { if (origin[i] != -1) { T.tree[i].parent = origin[i]; T.tree[i].weight = G.adjList[i].find(origin[i])->second; T.tree[origin[i]].children.insert(i); } } Weight oldw, w = T.pruneLeaves(G.terminalsMap); do { if (tle) break; oldw = w; apply_opt(T, G); w = T.pruneLeaves(G.terminalsMap); } while (oldw != w); if (tle) break; adjList = G.adjList; origin = full_backup_origin; min_distance = full_backup_distance; stack next; next.push(T.root); while (!next.empty()) { Vertex current = next.top(); next.pop(); for (set::iterator it = T.tree[current].children.begin(); it != T.tree[current].children.end(); ++it) { next.push(*it); min_distance[*it] = MAX_WEIGHT; origin[*it] = -1; adjList[current][*it] = 0; adjList[*it][current] = 0; } } if (tle) break; dijkstra(adjList, min_distance, origin, root); far_dist = 0; for (vector::const_iterator it = terminals.begin(); it != terminals.end(); ++it) { if (far_dist < min_distance[*it]) { far_dist = min_distance[*it]; far = *it; } } } // Build tree Tree T(G, root); for (unsigned int i = 0; i < G.adjList.size(); ++i) { if (origin[i] != -1) { T.tree[i].parent = origin[i]; T.tree[i].weight = G.adjList[i].find(origin[i])->second; T.tree[origin[i]].children.insert(i); } } return T; } bool cmp(const tuple &x, const tuple &y) { return get<0>(x) > get<0>(y); } Tree mst(const Graph &G, Vertex root) { Tree T(G, root); vector> active_vertices; for (pair neighbour : G.adjList[root]) { active_vertices.push_back( tuple(neighbour.second, root, neighbour.first)); } make_heap(active_vertices.begin(), active_vertices.end(), cmp); while (!active_vertices.empty()) { std::pop_heap(active_vertices.begin(), active_vertices.end(), cmp); tuple edge = active_vertices.back(); active_vertices.pop_back(); if (T.tree[get<2>(edge)].parent == -2) { T.tree[get<2>(edge)].parent = get<1>(edge); T.tree[get<2>(edge)].weight = get<0>(edge); T.tree[get<1>(edge)].children.insert(get<2>(edge)); for (pair neighbour : G.adjList[get<2>(edge)]) { if (T.tree[neighbour.first].parent == -2) { active_vertices.push_back(tuple( neighbour.second, get<2>(edge), neighbour.first)); push_heap(active_vertices.begin(), active_vertices.end(), cmp); } } } } return T; } Tree strong_bias_random(const Graph &G, Vertex root) { Tree T(G, root); default_random_engine generator; vector> active_vertices; for (pair neighbour : G.adjList[root]) { active_vertices.push_back( tuple(neighbour.second, root, neighbour.first)); } while (!active_vertices.empty()) { int position = uniform_int_distribution(0, active_vertices.size() - 1)(generator); tuple edge = active_vertices[position]; active_vertices[position] = active_vertices.back(); active_vertices.pop_back(); if (T.tree[get<2>(edge)].parent == -2) { T.tree[get<2>(edge)].parent = get<1>(edge); T.tree[get<2>(edge)].weight = get<0>(edge); T.tree[get<1>(edge)].children.insert(get<2>(edge)); for (pair neighbour : G.adjList[get<2>(edge)]) { if (T.tree[neighbour.first].parent == -2) { active_vertices.push_back(tuple( neighbour.second, get<2>(edge), neighbour.first)); push_heap(active_vertices.begin(), active_vertices.end(), cmp); } } } } return T; } Tree random(const Graph &G, Vertex root) { vector origin(G.adjList.size(), -2); origin[root] = -1; default_random_engine generator; for (Vertex t : G.terminals) { vector seen(G.adjList.size(), false); Vertex current = t; while (origin[current] == -2 || seen[current]) { seen[current] = true; int position = uniform_int_distribution( 0, G.adjList[current].size() - 1)(generator); map::const_iterator it = G.adjList[current].begin(); advance(it, position); Vertex next = it->first; origin[current] = next; current = next; } } Tree T(G, root); for (unsigned int i = 0; i < G.adjList.size(); ++i) { if (origin[i] > -1) { T.tree[i].parent = origin[i]; T.tree[i].weight = G.adjList[i].find(origin[i])->second; T.tree[origin[i]].children.insert(i); } } return T; }