2
https://leetcode.com/problems/sort-items-by-groups-respecting-dependencies/4
TC: O(n + m + E), E = No. of edges as seen from 'beforeItems' array7
Looking at the problem, it is clearly a topological sort problem. But there8
are two things that needs ordering. The nodes within a group can have an9
ordering, as well the groups.12
1. Topological sort for nodes alone.13
2. Topological sort for just the groups14
3. In order to do above, we create two graphs. One graph just for the groups15
with m nodes, where the nodes are actually the group IDs. Another graph with16
size n, it is for the graph nodes.17
4. Then perform topological sort for both the graphs.18
5. Once we have the ordered nodes after topological sort, we fill the nodes19
of each group with that order.20
6. Then using the topological order of groups, just fill the nodes for each26
vector<int> topologicalSort(vector<unordered_set<int>> &graph, vector<int> &indegree) {28
int processed = 0, n = graph.size();31
// Add 0 indegree nodes32
for (int node = 0; node < n; node++)33
if (indegree[node] == 0) q.emplace(node);36
auto node = q.front();41
order.emplace_back(node);43
// Remove its dependence44
for (auto neighbor : graph[node]) {46
if (indegree[neighbor] == 0) q.emplace(neighbor);50
return processed < n ? vector<int>{} : order;53
vector<int> sortItems(int n, int m, vector<int> &group, vector<vector<int>> &beforeItems) {54
// Each node without a group will be self contained in a new group with only55
// itself Set the new group id for each isolated node56
for (int node = 0; node < n; node++)57
if (group[node] == -1) group[node] = m++;59
// We create two graphs, one for the groups and another for the actual nodes60
vector<unordered_set<int>> group_graph(m), node_graph(n);61
// Stores the indegree for: Amongst Groups and nodes respectively62
vector<int> group_indegree(m, 0), node_indegree(n, 0);64
// Create cyclic graph for group and individual nodes65
for (auto node = 0; node < n; node++) {66
// Group to which the current node belongs67
int dst_group = group[node];68
// Source Groups on which the current node has a dependency69
for (auto src_node : beforeItems[node]) {70
int src_group = group[src_node];71
// check if the dependency is inter group or intra group72
// It is inter group dependency, make sure that the same dst_group was73
// not seen before, otherwise indegree will get additional 1, same logic75
if (dst_group != src_group && !group_graph[src_group].count(dst_group)) {76
group_graph[src_group].emplace(dst_group);77
++group_indegree[dst_group];80
// Add the dependency amongst the nodes81
if (!node_graph[src_node].count(node)) {82
node_graph[src_node].emplace(node);83
++node_indegree[node];88
// Perform topological sort at a node level89
vector<int> ordered_nodes = topologicalSort(node_graph, node_indegree);90
// Perform topological sort at a group level91
vector<int> ordered_groups = topologicalSort(group_graph, group_indegree);92
// Overall order of nodes95
// For each group, put the ordered nodes after topological sort96
vector<vector<int>> group_ordered_nodes(m);97
for (auto node : ordered_nodes) group_ordered_nodes[group[node]].emplace_back(node);99
// Now that within each group, all the nodes are ordered.100
// Using the topological sort info about the groups, just put the nodes in102
for (auto group : ordered_groups)103
for (auto node : group_ordered_nodes[group]) order.emplace_back(node);