LeetCode 1203. 项目管理

题目描述

1203. 项目管理

解法:双层拓扑排序

我们还是考虑示例 1,

在这里插入图片描述

第一步:完成项目和小组的对应关系

针对未接手的项目,我们不清楚具体将其分配给哪个小组,暂时存入栈 -1 中

在这里插入图片描述

我们进行如下的处理:

第一个未接手的项目分给栈 m m m,第二个未接手的项目分给栈 m + 1 m+1 m+1,以此类推,最坏情况下有 n n n 个未接手的项目,第 n n n 个未接手的项目分给栈 m + n m+n m+n

在这里插入图片描述
因为栈 2 、 3 、 4 2、3、4 234 可以和栈 0 0 0、栈 1 1 1 任意一个进行组合,所以按照排列组合有多种结果

第二步:根据映射关系,构建小组的关系图和项目的关系图

但是注意,并不是所有排列组合结果都是可行的,按照项目的先后关系,小组之间也会有一定的先后关系,所以形成了两张关系图

在这里插入图片描述

第三步:求小组关系的拓扑排序

同样我们对小组关系图进行拓扑排序,可以得到一个可行的结果,比如 < 0 , 1 , 2 , 3 , 4 > <0, 1, 2, 3, 4> <0,1,2,3,4>,根据拓扑排序结果,我们对应有如下的排列组合方式

在这里插入图片描述
当然比如说得到拓扑排序结果为 < 0 , 3 , 1 , 2 , 4 > <0, 3, 1, 2, 4> <0,3,1,2,4>,那么此时对应的排列组合方式为栈 0 0 0 和栈 3 3 3 组合在一起,对饮的解释就是项目 1 1 1 分给小组 0 0 0,这样也是完全可行的

第四步:拿着小组关系的拓扑排序结果,求同一小组内项目的拓扑排序

小组 0 0 0 的项目拓扑排序结果: < 6 , 3 , 4 > <6, 3, 4> <6,3,4>

小组 1 1 1 的项目拓扑排序结果: < 5 , 2 , 0 , 7 , 1 > <5, 2, 0, 7, 1> <5,2,0,7,1>

最终的一个可行的排序结果就是: < 6 , 3 , 4 , 5 , 2 , 0 , 7 , 1 > <6, 3, 4, 5, 2, 0, 7, 1> <6,3,4,5,2,0,7,1>

完整编码如下所示

class Solution {
public:

    vector<int> topSort(vector<int>& in_degree, vector<vector<int>>& g, vector<int>& items){
        queue<int> q;
        for(auto item: items)
            if(in_degree[item]==0) q.push(item);
        vector<int> res;
        while(!q.empty())
        {
            int u = q.front();
            q.pop();
            res.push_back(u);
            for(auto v: g[u])
                if(--in_degree[v]==0) q.push(v);
        }
        return (res.size()==items.size())?res:vector<int>{};
    }

    vector<int> sortItems(int n, int m, vector<int>& group, vector<vector<int>>& beforeItems) {
        vector<vector<int>> groupitem(n+m);

        vector<vector<int>> groupGraph(n+m);
        vector<vector<int>> itemGraph(n);

        vector<int> group_in_degree(n+m, 0);
        vector<int> item_in_degree(n, 0);

        vector<int> id;
        for(int i=0;i<n+m;i++) id.push_back(i);
        
        int leftid = m;
        for(int i=0;i<n;i++)
        {
            if(group[i]==-1)
            {
                group[i] = leftid;
                leftid += 1;
            }
            groupitem[group[i]].push_back(i);
        }

        for(int i=0;i<n;i++)
        {
            int cur_groupid = group[i];
            for(auto item: beforeItems[i])
            {
                int before_groupid = group[item];
                if(before_groupid==cur_groupid)
                {
                    item_in_degree[i] += 1;
                    itemGraph[item].push_back(i);
                }
                else
                {
                    group_in_degree[cur_groupid] += 1;
                    groupGraph[before_groupid].push_back(cur_groupid);
                }
            }
        }

        vector<int> groupTopSort = topSort(group_in_degree, groupGraph, id);
        if(groupTopSort.size()==0) return vector<int>{};

        vector<int> ans;
        for(auto cur_groupid: groupTopSort)
        {
            int size = groupitem[cur_groupid].size();
            if(size==0) continue;
            vector<int> res = topSort(item_in_degree, itemGraph, groupitem[cur_groupid]);
            if(res.size()==0) return vector<int>{};
            for(auto item: res) ans.push_back(item);
        }
        return ans;
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值