思路
个人认为,拓扑排序的重点在于反过来想,若干菜中,一个菜由若干个材料制成,即若干材料中,一个材料是若干个菜的组成部分。
先统计每个材料可以做那些菜,即材料到菜的边,并记录每个菜需要多少种材料,即入度;
之后,当扫到一条材料到菜的边,即找到这个菜的一种材料,这个菜的入度减一,当这个菜的入度为0,即这个菜所需的材料都找齐了,加入答案,并将这个菜加入材料队列中。
实现上,用队列存储材料,初始时将所有给定原材料入队,之后遍历由该材料组成的菜,将他们的入度减一,并进行是否完成的判断。
代码
class Solution {
public:
vector<string> findAllRecipes(vector<string>& recipes, vector<vector<string>>& ingredients, vector<string>& supplies) {
unordered_map<string, vector<string>> edges;
unordered_map<string, int> in;
for(int i = 0; i < recipes.size(); i++) {
in[recipes[i]] = ingredients[i].size();
for(int j = 0; j < ingredients[i].size(); j++)
edges[ingredients[i][j]].push_back(recipes[i]);
}
queue<string> q;
for(auto x : supplies) q.push(x);
vector<string> ans;
while(!q.empty()) {
string cailiao = q.front();
q.pop();
if(edges.find(cailiao) == edges.end())continue;
for(auto cai : edges[cailiao]) {
in[cai]--;
if(in[cai] == 0) {
q.push(cai);
ans.push_back(cai);
}
}
}
return ans;
}
};