leetcode-1203. 项目管理之拓扑排序

题目

在这里插入图片描述

分析

从题目可以比较简单的看出要使用拓扑排序,显然是需要对item建立图结构的,容易得到item的拓扑排序序列。但是题目要求:同一小组的项目,排序后在列表中彼此相邻!怎么理解这个条件呢?也就是说,属于同一个小组的项目必要可以独立的拎出来,不需要依赖别的小组的进度!假如小组A的部分依赖于小组B,而小组B也有部分依赖于小组A,那么其拓扑排序必定是:B --> A --> B,而无法做到题目要求的同一小组的项目,排序后在列表中彼此相邻。因此为了确定小组间的顺序,我们需要将各个小组要构建图结构,要求其小组结构无环并按拓扑排序输出!然后我们就可以根据小组的拓扑顺序来分别对各个小组内的项目再进行拓扑排序输出!
还有一点很重要的是,因为group = -1的项目不属于任何小组,因此他们不需要满足彼此相邻的条件。但是他们也不能随意的排序,因为存在一些有小组的项目是依赖于没有小组的项目的!因此我们可以对group = -1的item进行group再分配,为他们分配独立的group号!

代码

class Solution {
public:
    vector<int> TopSort(vector<vector<int>>& graph, vector<int>& list, vector<int>& indegree){
        vector<int> res;
        queue<int> q;
        for(int i=0;i<list.size();i++){
            if(indegree[list[i]] == 0)
                q.push(list[i]);
        }

        while(!q.empty()){
            int tmp = q.front();
            for(int i=0;i<graph[tmp].size();i++){
                indegree[graph[tmp][i]]--;
                if(indegree[graph[tmp][i]] == 0 && find(list.begin(),list.end(),graph[tmp][i])!=list.end()) // 这里是为了确保只有属于list的顶点被入队排序
                    q.push(graph[tmp][i]);
            }
            q.pop();
            res.push_back(tmp);
        }
        
        if(res.size() == list.size())
            return res;
        else{
            res.resize(0);
            return res; 
        }
    }

    vector<int> sortItems(int n, int m, vector<int>& group, vector<vector<int>>& beforeItems) {
        // 对于group = -1的item来说为其分配新的group号!关键!
        for(int i=0;i<n;i++){
            if(group[i] == -1){
                group[i] = m;
                m++;
            }
        }

        // 对不同group的item进行分类
        vector<vector<int>> groupItem(m,vector(0,0));
        for(int i=0;i<n;i++){
            groupItem[group[i]].push_back(i);
        }

        vector<vector<int>> itemGraph(n,vector<int>(0,0));
        vector<vector<int>> groupGraph(m,vector<int>(0,0));
        vector<int> itemIndegree(n,0);
        vector<int> groupIndegree(m,0);
        
        // 记录group的图结构以及group的入度
        for(int i=0;i<beforeItems.size();i++){
            int currentGroup = group[i];
            for(int j=0;j<beforeItems[i].size();j++){
                int beforeGroup = group[beforeItems[i][j]];
                if(beforeGroup!=currentGroup){
                    groupGraph[beforeGroup].push_back(currentGroup);
                    groupIndegree[currentGroup]++;
                }
                // 下面是对于find(list.begin(),list.end(),graph[tmp][i])!=list.end()的优化,但是不太好理解,用于防止不属于某一group的顶点被Top排序
                // else{
                //     itemGraph[beforeItems[i][j]].push_back(i);
                //     itemIndegree[i]++;
                // }
            }
        }

		// 记录item的图结构以及item的入度
        for(int i=0;i<beforeItems.size();i++){
            for(int j=0;j<beforeItems[i].size();j++){
                itemGraph[beforeItems[i][j]].push_back(i);
                    itemIndegree[i]++;
                }
        }

        // 获取group关系的拓扑排序
        vector<int> groupList(m,0);
        for(int i=0;i<m;i++)
            groupList[i] = i;
        vector<int> groupTopSort = TopSort(groupGraph,groupList,groupIndegree);
        if(groupTopSort.size() == 0){
            return groupTopSort;
        }
        
		// 对各个group内的item们进行top排序
        vector<int> res;
        for(int i=0;i<groupTopSort.size();i++){
            vector<int> itemTopSort = TopSort(itemGraph,groupItem[groupTopSort[i]],itemIndegree);
            if(itemTopSort.size() == 0 && groupItem[groupTopSort[i]].size()!=0)
                return itemTopSort;
            else{
                for(int m=0;m<itemTopSort.size();m++)
                    res.push_back(itemTopSort[m]);
            }
        }

        return res;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值