- 拓扑排序问题解决
在一个顶点活动图(有向无环图)中找到完成任务的先后顺序,这个顺序可能不是唯一的 - 如何排序?
a. 找出图中入度为 0 的点,然后输出
b. 删除与该点相连的边
c. 重复a,b操作,直到图中没有点或入度为 0 的点(因为图中有可能有环)为止
拓扑排序一个重要应用就有:判断有向图是否有环
- 如何实现拓扑排序?
借助队列,来一次 BFS
把所有入度为 0 的点加入到队列中
当队列不为空时一直循环
拿出对头元素,加入到最终结果中
删除与该元素相连的边
判断与删除的边相连的点,其入度是否变为 0
如果入度为 0,加入到队列中
// 入度和出度全都在 course_map
class Solution {
unordered_multimap<int, int> course_map;
queue<int> q;
public:
void bfs() {
while (!q.empty()) {
int front = q.front();
q.pop();
for (auto it = course_map.begin(); it != course_map.end();) {
if (it->second == front) {
int i = it->first;
it = course_map.erase(it);
if (course_map.count(i) == 0) {
q.push(i);
}
}
else {
++it;
}
}
}
}
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
for (auto& v : prerequisites) {
course_map.insert({v[0], v[1]});
}
for (int i = 0; i < numCourses; ++i) {
if (course_map.count(i) == 0) {
q.push(i);
}
}
bfs();
return course_map.empty();
}
};
// 将入度和出度分开
class Solution {
unordered_map<int, vector<int>> edges; // 标记出度
vector<int> in; // 标记入度
queue<int> q; // 为 0 的入度
public:
void bfs() {
while (!q.empty()) {
int front = q.front();
q.pop();
vector<int>& out = edges[front];
for (int e : out) {
in[e]--;
if (in[e] == 0) {
q.push(e);
}
}
edges.erase(front);
}
}
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
in = vector<int>(numCourses, 0);
for (auto& e : prerequisites) {
edges[e[1]].push_back(e[0]); // e[1] -> e[0]
in[e[0]]++;
}
for (int i = 0; i < numCourses; ++i) {
if (in[i] == 0) {
q.push(i);
}
}
bfs();
return edges.empty();
}
};
class Solution {
unordered_map<int, vector<int>> edges; // 标记出度
vector<int> in; // 标记入度
queue<int> q; // 为 0 的入度
vector<int> ret;
public:
void bfs() {
while (!q.empty()) {
int front = q.front(); q.pop();
ret.push_back(front);
auto& out = edges[front];
for (int e : out) {
in[e]--;
if (in[e] == 0) {
q.push(e);
}
}
edges.erase(front);
}
}
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
in = vector<int>(numCourses, 0);
for (auto& e : prerequisites) {
edges[e[1]].push_back(e[0]); // e[1] -> e[0]
in[e[0]]++;
}
for (int i = 0; i < numCourses; ++i) {
if (in[i] == 0) {
q.push(i);
}
}
bfs();
return edges.empty() ? ret : vector<int>();
}
};
class Solution {
unordered_map<char, unordered_set<char>> edges; // 标记出度
unordered_map<char, int> in; // 标记入度
queue<char> q;
string ret;
public:
void bfs() {
while (!q.empty()) {
char front = q.front(); q.pop();
ret += front;
auto& out = edges[front];
for (char c : out) {
if (--in[c] == 0) {
q.push(c);
}
}
edges.erase(front);
}
}
string alienOrder(vector<string>& words) {
for (string& word : words) {
for (char c : word) {
in[c] = 0;
}
}
for (int i = 0; i < words.size(); ++i) {
for (int j = i + 1; j < words.size(); ++j) {
for (int k = 0; k < words[i].size(); ++k) {
if (k >= words[j].size()) return "";
if (words[i][k] != words[j][k]) {
if (edges.count(words[i][k]) == 0
|| edges[words[i][k]].count(words[j][k]) == 0) {
edges[words[i][k]].insert(words[j][k]);
in[words[j][k]]++;
}
break;
}
}
}
}
for (auto& e : in) {
if (e.second == 0) {
q.push(e.first);
}
}
bfs();
return edges.empty() ? ret : "";
}
};