题目描述
解法:双层拓扑排序
我们还是考虑示例 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
2、3、4 可以和栈
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;
}
};