基础与模板:
有两个Kahn
和DFS
两个算法
下面给出Kahn
的算法模板
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
vector<int> topologicalSortKahn(int num, const vector<pair<int, int>>& relations){
vector<int> result;
vector<int> inDegree(num+1,0); // 记录所有节点的入度
vector<vector<int>> adj(num+1); // 用于记录节点的连接的节点
for(const auto &rel:relations){
int from = rel.first;
int to = rel.second;
adj[from].push_back(to); // 写入每个节点连接的节点
inDegree[to]++; // 写入入度
}
queue<int> q; // 用于记录入度为0的节点
// 遍历节点,把入度为0的点写入q
// 这里需要注意节点到底是从0开始还是从1开始
for(int i = 0;i< num;++i){
if(inDegree[i] == 0){
q.push(i);
}
}
// 提取入度为0的节点,删除其连接,不断更新入度
while(!q.empty()){
int current= q.front();
q.pop();
result.push_back(current);
for(int next : adj[current]){
inDegree[next]--; // 每个下一节点的入度减1
if(inDegree[next]==0){ // 入度减1后判断为0加入q
q.push(next);
}
}
}
if(result.size() != num) return{-1}; // 判断是环,返回-1
return result;
}
int main(){
int N,M;
cin>>N>>M;
vector<pair<int,int>> inRelation;
int from,to;
while(M--){
cin>>from>>to;
inRelation.emplace_back(pair<int,int>{from,to});
}
vector<int> res = topologicalSortKahn(N,inRelation);
for(size_t i = 0;i < res.size()-1;i++){
cout<<res[i]<<" ";
}
cout<<res.back();
}
图的拓扑排序题目
leetcode
题号 标题 题解 标签 难度 0207 课程表 Python 深度优先搜索、广度优先搜索、图、拓扑排序 中等 0210 课程表 II Python 深度优先搜索、广度优先搜索、图、拓扑排序 中等 1136 并行课程 Python 图、拓扑排序 中等 2050 并行课程 III Python 图、拓扑排序、数组、动态规划 困难 0802 找到最终的安全状态 Python 深度优先搜索、广度优先搜索、图、拓扑排序 中等 0851 喧闹和富有 Python 深度优先搜索、图、拓扑排序、数组 中等
题目1、117. 软件构建
卡吗网代码编辑真不错
直接套模板
题目2、210. 课程表 II
class Solution {
public:
vector<int> findOrder(int numCourses, vector<vector<int>>& prerequisites) {
vector<int> result;
vector<int> inDegree(numCourses+1,0); // 记录所有节点的入度
vector<vector<int>> adj(numCourses+1); // 用于记录节点的连接的节点
for(const auto &rel:prerequisites){
int from = rel[0];
int to = rel[1];
adj[from].push_back(to); // 写入每个节点连接的节点
inDegree[to]++; // 写入入度
}
queue<int> q; // 用于记录入度为0的节点
// 遍历节点,把入度为0的点写入q
// 这里需要注意节点到底是从0开始还是从1开始
for(int i = 0;i< numCourses;++i){
if(inDegree[i] == 0){
q.push(i);
}
}
// 提取入度为0的节点,删除其连接,不断更新入度
while(!q.empty()){
int current= q.front();
q.pop();
result.push_back(current);
for(int next : adj[current]){
inDegree[next]--; // 每个下一节点的入度减1
if(inDegree[next]==0){ // 入度减1后判断为0加入q
q.push(next);
}
}
}
if(result.size() != static_cast<size_t>(numCourses)) return{}; // 判断是环,返回{}
return result;
}
};
题目3、任务调度算法

#include <vector>
#include <utility>
#include <queue>
#include <algorithm>
using namespace std;
class Solution {
public:
int GetMinT ime(int taskNum, const vector<pair<int, int>>& relations)
{
vector<vector<int>> adj(taskNum+1);
vector<int> inDegree(taskNum + 1, 0);
vector<int> dp(taskNum + 1, 1);
for (const auto& rel : relations) {
int from = rel.second;
int to = rel.first;
adj[from].push_back(to);
inDegree[to]++;
}
queue<int> q;
for (int i = 1; i <= taskNum; ++i) {
if (inDegree[i] == 0) {
q.push(i);
}
}
while (!q.empty()) {
int current = q.front();
q.pop();
for (int next : adj[current]) {
dp[next] = max(dp[next], dp[current] + 1);
if (--inDegree[next] == 0) {
q.push(next);
}
}
}
return *max_element(dp.begin() + 1, dp.end());
}
};
题目4、207. 课程表 - 力扣
这里就是判断是否有环
题目5、802. 找到最终的安全状态
拓扑排序适用条件是:有向无环图
当处理有环图时,
采用拓扑排序最终得到的结果vector里面都是入度为0的节点
所以,从入度为0的节点依次向前找,每次循环之后入度为0的节点
这个题目,只需把出度换成入度,再使用拓扑排序处理有向有环图即可
注意from和to的设置即可,后面就是套模板
题目6、851. 喧闹和富有

构建有向无环图,从一侧开始