1203. 项目管理 双重拓扑排序

思路

执行用时:180 ms, 在所有 C++ 提交中击败了30.89%的用户

内存消耗:49.9 MB, 在所有 C++ 提交中击败了68.58%的用户

[题解](🎦 1203. 项目管理 - 项目管理 - 力扣(LeetCode) (leetcode-cn.com))

这题的关键就是想到首先要给组进行拓扑排序。

时间复杂度分析

一次遍历给-1的不需要合作的项目分配组好 O ( n ) O(n) O(n)

两次建图O(n)

两次拓扑排序 O ( n + e ) O(n+e) O(n+e),遍历所有的点+边

一次合并 O ( n ) O(n) O(n)

总的时间复杂度 O ( n + e ) O(n+e) O(n+e)

大概是这样

代码

// n projects, m groups
// Firstly, projects belong to same group need to be in one group
// Secondly, projects in one group need to satisfy topological order
// In this way,the problems can be transferred to two topological problems

// How can we get topological order of groups?
// from vector group,we find that each project beglongs to a group or group[i]=-1 means project belongs to no group
// from beforeItems we get topological order of project
// so we can get topological order of groups

// How can we get topological order of items?
// directly through topological sort

// How can we get topological order in each group
// Firstly, we traverse topological items, for each item A, we get group of that item group[A];
// then we directly push_back this item to this group.

class Solution {
public:
    int beforeItemsSize;
    vector<int> sortItems(int n, int m, vector<int>& group, vector<vector<int>>& beforeItems) {
        beforeItemsSize = beforeItems.size();

        // allocate group id to projects that belongs to no group
        for (int i = 0; i < n; i++) {
            if (group[i] == -1) {
                group[i] = m++;
            }
        }

        // establish graph
        vector<vector<int>>groupsGraph(m);
        vector<vector<int>>itemsGraph(n);
        vector<int>indegreesGroups(m,0), indegreesItems(n,0);
        for (int i = 0; i < n; i++) {
            int& curItem = i;
            int& curGroup = group[i];
            for (auto& beforeItem : beforeItems[i]) {
                itemsGraph[beforeItem].push_back(curItem);
                indegreesItems[curItem]++;

                int& beforeGroup = group[beforeItem];
                if (beforeGroup == curGroup) {
                    continue;
                }
                else {
                    groupsGraph[beforeGroup].push_back(curGroup);
                    indegreesGroups[curGroup]++;
                }
            }
        }
        
        // topological sort
        vector<int>topologicalGroups = topologicalSort(groupsGraph,indegreesGroups);
        if (topologicalGroups.size() == 0) {
            return vector<int>();
        }

        vector<int>topologicalItems = topologicalSort(itemsGraph,indegreesItems);
        if (topologicalItems.size() == 0) {
            return vector<int>();
        }
        
        vector<vector<int>>groups(m);
        // topological sort in each group
        for (int i = 0; i < n; i++) {
            int& curItem = topologicalItems[i];
            int curGroup = group[curItem];
            groups[curGroup].push_back(curItem);
        }

        vector<int>res;

        for (int i = 0; i < m; i++) {
            int curGroup = topologicalGroups[i];
            for (auto& curItem : groups[curGroup]) {
                res.push_back(curItem);
            }
        }
        return res;

    }
    vector<int> topologicalSort(vector<vector<int>>graphs, vector<int> indegrees) {
        int n = graphs.size();
        queue<int>q;
        for (int i = 0; i < n; i++) {
            if (indegrees[i] == 0) {
                q.push(i);
            }
        }
        int cnt = 0;
        vector<int>res;
        while (!q.empty()) {
            int from = q.front();
            q.pop();
            res.push_back(from);
            cnt++;
            for (auto& to : graphs[from]) {
                if (indegrees[to] <= 0) {
                    continue;
                }
                if (--indegrees[to] == 0) {
                    q.push(to);
                }
            }
        }
        if (cnt < n) {
            return vector<int>();
        }
        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值