LeetCode 2192. 有向无环图中一个节点的所有祖先
给你一个正整数 n
,它表示一个 有向无环图 中节点的数目,节点编号为 0
到 n - 1
(包括两者)。
给你一个二维整数数组 edges
,其中 edges[i] = [fromi, toi]
表示图中一条从 fromi
到 toi
的单向边。
请你返回一个数组 answer
,其中 answer[i]
是第 i
个节点的所有 祖先 ,这些祖先节点 升序 排序。
如果 u
通过一系列边,能够到达 v
,那么我们称节点 u
是节点 v
的 祖先 节点。
示例 1:
输入:n = 8, edgeList = [[0,3],[0,4],[1,3],[2,4],[2,7],[3,5],[3,6],[3,7],[4,6]]
输出:[[],[],[],[0,1],[0,2],[0,1,3],[0,1,2,3,4],[0,1,2,3]]
解释:
上图为输入所对应的图。
- 节点 0 ,1 和 2 没有任何祖先。
- 节点 3 有 2 个祖先 0 和 1 。
- 节点 4 有 2 个祖先 0 和 2 。
- 节点 5 有 3 个祖先 0 ,1 和 3 。
- 节点 6 有 5 个祖先 0 ,1 ,2 ,3 和 4 。
- 节点 7 有 4 个祖先 0 ,1 ,2 和 3 。
method: 拓扑排序
vector<vector<int>> getAncestors(int n, vector<vector<int>>& edges) {
vector<unordered_set<int>> anc(n); // set去重
vector<vector<int>> e(n);
vector<int> indegree(n);
for (auto& t : edges) {
e[t[0]].push_back(t[1]); // t[0] -> t[1]
indegree[t[1]]++;
}
queue<int> q;
for (int i = 0; i < n; i++) {
if (indegree[i] == 0) q.push(i);
}
while (!q.empty()) {
int x = q.front();
q.pop();
for (auto& v : e[x]) {
anc[v].insert(x); // 当前节点成为其后继节点的祖先
for (auto t : anc[x]) {
anc[v].insert(t); // 当前节点的祖先也是其后继节点的祖先
}
if (--indegree[v] == 0) q.push(v);
}
}
vector<vector<int>> res;
for (int i = 0; i < n; i++) {
vector<int> vec;
for (auto t : anc[i]) vec.push_back(t);
sort(vec.begin(), vec.end());
res.push_back(vec);
}
return res;
}