From 1e0f57cae88c2fbaf4ac7e2f1740a522a35855da Mon Sep 17 00:00:00 2001 From: br1b0 Date: Sat, 20 Dec 2014 18:49:42 +0100 Subject: [PATCH 1/2] Added a much faster cpp version I added basic pruning so recursion won't be called if the best path using the rest of unvisited nodes cannot possibly improve the current solution. --- cpp.cpp | 81 +++++++++++++++++++++++++++++++++++++++------------------ 1 file changed, 56 insertions(+), 25 deletions(-) diff --git a/cpp.cpp b/cpp.cpp index 5eae2f2..b2236e2 100644 --- a/cpp.cpp +++ b/cpp.cpp @@ -5,6 +5,7 @@ #include #include #include +#include using namespace std; using namespace std::chrono; @@ -25,42 +26,72 @@ vector readPlaces(){ while (text >> node >> neighbour >> cost){ nodes[node].neighbours.push_back(route{neighbour, cost}); } + for (auto &n : nodes) { + sort(n.neighbours.begin(), n.neighbours.end(), + [](const route &a, const route &b) { + return a.cost > b.cost; + }); + } return nodes; } -template -int getLongestPath(const vector &nodes, const int nodeID, bitset visited){ +static int getMaxCost(const vector &nodes, + const vector &visited) { + int result = 0; + int lowestMaxNodeCost = 0; + for (int i = 0; i < (int) nodes.size(); ++i) { + if (visited[i]) { + continue; + } + int maxNodeCost = 0; + for (const route &neighbour : nodes[i].neighbours) { + if (visited[neighbour.dest]) { + continue; + } + if (neighbour.cost > maxNodeCost) { + maxNodeCost = neighbour.cost; + } + } + if (maxNodeCost < lowestMaxNodeCost) { + lowestMaxNodeCost = maxNodeCost; + } + result += maxNodeCost; + } + return result - lowestMaxNodeCost; +} + +static void getLongestPath(int remainingNodes, + int nodeID, + int curPathLen, + const vector &nodes, + vector &visited, + int &maxPathLen) { + if (!remainingNodes) { + if (curPathLen > maxPathLen) { + maxPathLen = curPathLen; + } + return; + } visited[nodeID] = true; - int max=0; - for(const route &neighbour: nodes[nodeID].neighbours){ - if (visited[neighbour.dest] == false){ - const int dist = neighbour.cost + getLongestPath(nodes, neighbour.dest, visited); - if (dist > max){ - max = dist; + int nextMaxCost = getMaxCost(nodes, visited); + for (const route &neighbour : nodes[nodeID].neighbours) { + if (!visited[neighbour.dest]) { + int nextPathLen = curPathLen + neighbour.cost; + if (nextPathLen + nextMaxCost > maxPathLen) { + getLongestPath(remainingNodes - 1, neighbour.dest, nextPathLen, + nodes, visited, maxPathLen); } } } visited[nodeID] = false; - return max; } -int getLongestPath(const vector &nodes) +static int getLongestPath(const vector &nodes) { - if (nodes.size() <= 16) { - return getLongestPath<16>(nodes, 0, bitset<16>()); - } else if (nodes.size() <= 256) { - return getLongestPath<256>(nodes, 0, bitset<256>()); - } else if (nodes.size() <= 4096) { - return getLongestPath<4096>(nodes, 0, bitset<4096>()); - } else if (nodes.size() <= 65536) { - return getLongestPath<65536>(nodes, 0, bitset<65536>()); - } else if (nodes.size() <= 1048576) { - return getLongestPath<1048576>(nodes, 0, bitset<1048576>()); - } else if (nodes.size() <= 16777216) { - return getLongestPath<16777216>(nodes, 0, bitset<16777216>()); - } else { - return -1; - } + vector visited(nodes.size()); + int maxPathLen = 0; + getLongestPath(nodes.size() - 1, 0, 0, nodes, visited, maxPathLen); + return maxPathLen; } int main(int argc, char** argv){ From a19674b3d81cc04e429edead819b7532b814f963 Mon Sep 17 00:00:00 2001 From: br1b0 Date: Sun, 21 Dec 2014 18:04:24 +0100 Subject: [PATCH 2/2] Moved cpp implementation with pruning to cpppruned.cpp. --- cpp.cpp | 81 ++++++++++++--------------------------- cpppruned.cpp | 104 ++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 129 insertions(+), 56 deletions(-) create mode 100644 cpppruned.cpp diff --git a/cpp.cpp b/cpp.cpp index b2236e2..5eae2f2 100644 --- a/cpp.cpp +++ b/cpp.cpp @@ -5,7 +5,6 @@ #include #include #include -#include using namespace std; using namespace std::chrono; @@ -26,72 +25,42 @@ vector readPlaces(){ while (text >> node >> neighbour >> cost){ nodes[node].neighbours.push_back(route{neighbour, cost}); } - for (auto &n : nodes) { - sort(n.neighbours.begin(), n.neighbours.end(), - [](const route &a, const route &b) { - return a.cost > b.cost; - }); - } return nodes; } -static int getMaxCost(const vector &nodes, - const vector &visited) { - int result = 0; - int lowestMaxNodeCost = 0; - for (int i = 0; i < (int) nodes.size(); ++i) { - if (visited[i]) { - continue; - } - int maxNodeCost = 0; - for (const route &neighbour : nodes[i].neighbours) { - if (visited[neighbour.dest]) { - continue; - } - if (neighbour.cost > maxNodeCost) { - maxNodeCost = neighbour.cost; - } - } - if (maxNodeCost < lowestMaxNodeCost) { - lowestMaxNodeCost = maxNodeCost; - } - result += maxNodeCost; - } - return result - lowestMaxNodeCost; -} - -static void getLongestPath(int remainingNodes, - int nodeID, - int curPathLen, - const vector &nodes, - vector &visited, - int &maxPathLen) { - if (!remainingNodes) { - if (curPathLen > maxPathLen) { - maxPathLen = curPathLen; - } - return; - } +template +int getLongestPath(const vector &nodes, const int nodeID, bitset visited){ visited[nodeID] = true; - int nextMaxCost = getMaxCost(nodes, visited); - for (const route &neighbour : nodes[nodeID].neighbours) { - if (!visited[neighbour.dest]) { - int nextPathLen = curPathLen + neighbour.cost; - if (nextPathLen + nextMaxCost > maxPathLen) { - getLongestPath(remainingNodes - 1, neighbour.dest, nextPathLen, - nodes, visited, maxPathLen); + int max=0; + for(const route &neighbour: nodes[nodeID].neighbours){ + if (visited[neighbour.dest] == false){ + const int dist = neighbour.cost + getLongestPath(nodes, neighbour.dest, visited); + if (dist > max){ + max = dist; } } } visited[nodeID] = false; + return max; } -static int getLongestPath(const vector &nodes) +int getLongestPath(const vector &nodes) { - vector visited(nodes.size()); - int maxPathLen = 0; - getLongestPath(nodes.size() - 1, 0, 0, nodes, visited, maxPathLen); - return maxPathLen; + if (nodes.size() <= 16) { + return getLongestPath<16>(nodes, 0, bitset<16>()); + } else if (nodes.size() <= 256) { + return getLongestPath<256>(nodes, 0, bitset<256>()); + } else if (nodes.size() <= 4096) { + return getLongestPath<4096>(nodes, 0, bitset<4096>()); + } else if (nodes.size() <= 65536) { + return getLongestPath<65536>(nodes, 0, bitset<65536>()); + } else if (nodes.size() <= 1048576) { + return getLongestPath<1048576>(nodes, 0, bitset<1048576>()); + } else if (nodes.size() <= 16777216) { + return getLongestPath<16777216>(nodes, 0, bitset<16777216>()); + } else { + return -1; + } } int main(int argc, char** argv){ diff --git a/cpppruned.cpp b/cpppruned.cpp new file mode 100644 index 0000000..b2236e2 --- /dev/null +++ b/cpppruned.cpp @@ -0,0 +1,104 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +using namespace std; +using namespace std::chrono; + +struct route{ + int dest, cost; +}; + +struct node { + vector neighbours; +}; + +vector readPlaces(){ + ifstream text("agraph"); + int numNodes; text >> numNodes; + vector nodes(numNodes); + int node, neighbour, cost; + while (text >> node >> neighbour >> cost){ + nodes[node].neighbours.push_back(route{neighbour, cost}); + } + for (auto &n : nodes) { + sort(n.neighbours.begin(), n.neighbours.end(), + [](const route &a, const route &b) { + return a.cost > b.cost; + }); + } + return nodes; +} + +static int getMaxCost(const vector &nodes, + const vector &visited) { + int result = 0; + int lowestMaxNodeCost = 0; + for (int i = 0; i < (int) nodes.size(); ++i) { + if (visited[i]) { + continue; + } + int maxNodeCost = 0; + for (const route &neighbour : nodes[i].neighbours) { + if (visited[neighbour.dest]) { + continue; + } + if (neighbour.cost > maxNodeCost) { + maxNodeCost = neighbour.cost; + } + } + if (maxNodeCost < lowestMaxNodeCost) { + lowestMaxNodeCost = maxNodeCost; + } + result += maxNodeCost; + } + return result - lowestMaxNodeCost; +} + +static void getLongestPath(int remainingNodes, + int nodeID, + int curPathLen, + const vector &nodes, + vector &visited, + int &maxPathLen) { + if (!remainingNodes) { + if (curPathLen > maxPathLen) { + maxPathLen = curPathLen; + } + return; + } + visited[nodeID] = true; + int nextMaxCost = getMaxCost(nodes, visited); + for (const route &neighbour : nodes[nodeID].neighbours) { + if (!visited[neighbour.dest]) { + int nextPathLen = curPathLen + neighbour.cost; + if (nextPathLen + nextMaxCost > maxPathLen) { + getLongestPath(remainingNodes - 1, neighbour.dest, nextPathLen, + nodes, visited, maxPathLen); + } + } + } + visited[nodeID] = false; +} + +static int getLongestPath(const vector &nodes) +{ + vector visited(nodes.size()); + int maxPathLen = 0; + getLongestPath(nodes.size() - 1, 0, 0, nodes, visited, maxPathLen); + return maxPathLen; +} + +int main(int argc, char** argv){ + auto nodes = readPlaces(); + auto start = high_resolution_clock::now(); + int len = getLongestPath(nodes); + auto end = high_resolution_clock::now(); + auto duration = (int)(0.001 * duration_cast(end - start).count()); + cout << len << " LANGUAGE C++ " << duration << std::endl; +}