diff --git a/minimum-spanning-tree.cpp b/minimum-spanning-tree.cpp new file mode 100644 index 0000000..ef6c752 --- /dev/null +++ b/minimum-spanning-tree.cpp @@ -0,0 +1,114 @@ +class MST +{ + /** + * Minumum Spanning Tree + * + */ + +private: + vector _pre; // pre-node + vector _size; // size of node + + /*! + * @brief : finding function of union set + * @param [x] : node index + * @retval : parent node + */ + int find(int x) + { + if (_pre[x] == x) + return x; + _pre[x] = find(_pre[x]); + return _pre[x]; + } +public: + /*! + * @brief : prim minimum spanning tree algorithm + * @param [num_nodes] : number of nodes + * @param [connections] : inter-node connection distance [start£¬end£¬distance] + * @retval : minimum weighted-sum + */ + int prim(int num_nodes, vector>& connections) + { + vector>> edges(n); + for (size_t i = 0; i < connections.size(); i++) { + int city_a = connections[i][0], city_b = connections[i][1]; + int cost = connections[i][2]; + edges[city_a].push_back(make_pair(city_b, cost)); + edges[city_b].push_back(make_pair(city_a, cost)); + } + set intree; // set of visited node + vector> out_edges; // external edge + out_edges.push_back(make_pair(0, 0)); // target node + + int ans = 0; + + // iterate over all outward expanding edges until all nodes are visited + while (out_edges.size() != 0 && intree.size() != num_nodes) + { + // find the edge with minimal weight + vector>::iterator iter = min_element(out_edges.begin(), out_edges.end(), [&](pair& elem1, pairelem2) + { + return elem1.second < elem2.second; + + }); + pair out_edge = *iter; + out_edges.erase(iter); + + // add unvisited node + if (intree.find(out_edge.first) == intree.end()) + { + intree.insert(out_edge.first); + ans += out_edge.second; + for (pair edge : edges[out_edge.first]) + { + out_edges.push_back(make_pair(edge.first, edge.second)); + } + } + } + + if (intree.size() != num_nodes) + return -1; // not exist if two nodes is not connected + return ans; + } + + + /*! + * @brief : Kruskal MST algorithm + * @param [num_nodes] : Number of nodes + * @param [connections] : Inter-node connection distance [start£¬end£¬distance] + * @retval : Minimum weighted-sum + */ + int kruskal(int numNodes, vector>& connections) + _pre.resize(numNodes), _size.resize(numNodes, 1); + iota(_pre.begin(), _pre.end(), 0); + + // sort with the distance + sort(connections.begin(), connections.end(), [&](vector& elem1, vector& elem2) { + return elem1.at(2) < elem2.at(2); + }); + + int ans = 0; // minimum weighted-sum + int edge_count = 0; // number of visited nodes + for (size_t i = 0; i < connections.size(); i++) { + int x = find(connections[i][0]), y = find(connections[i][1]); + + // Union find set + if (x != y) { + if (_size[x] > _size[y]) { + swap(x, y); + } + + _pre[x] = y; + _size[y] += _size[x]; + ans += connections[i][2]; + edge_count++; + if (edge_count == numNodes - 1) { + return ans; + } + } + } + + return -1; // not exist if two nodes is not connected + } +}; \ No newline at end of file diff --git a/topological-sorting.cpp b/topological-sorting.cpp new file mode 100644 index 0000000..b62ed52 --- /dev/null +++ b/topological-sorting.cpp @@ -0,0 +1,72 @@ +class Solution +{ +private: + enum class STATUS + { + UN_VISITED, + IN_SEARCHING, + FINISHED + }; + + vector> edges; + vector visited; + vector sequence; + + bool find_cycle = false; // cycle + + /** + * @brief deep first search + * @param[in] node index + * + */ + void deepFirstSearch(int node) + { + visited[node] = Status::SEARCHING; + for (int neighbor : edges[node]) { + if (visited[neighbor] == Status::UNVISITED) { + deepFirstSearch(neighbor); + if (find_cycle) { + return; // unsolvable + } + } + else if (visited[neighbor] == Status::SEARCHING) { + find_cycle = true; + return; + } + } + visited[node] = Status::FINISH; + sequence.push_back(node); + } + +public: + /** + * @brief topological sequence + * @param[in] number of nodes + * @param[in] node connection + * @retval sequence + */ + vector findTopologicalOrder(int numNodes, vector>& linkage) + { + edges.resize(numNodes); + visited.resize(numNodes, Status::UNVISITED); + + // generate adjacency list + for (const auto& info : linkage) { + edges[info[1]].push_back(info[0]); + } + + // deep first search to determine the topological sequence + for (int i = 0; i < numNodes && !find_cycle; ++i) { + if (visited[i] == Status::UNVISITED) { + deepFirstSearch(i); + } + } + + if (find_cycle) { + return vector(); // unsolvable for cycle + } + + reverse(sequence.begin(), sequence.end()); + return sequence; + } +}; \ No newline at end of file