数据结构与算法:图论——拓扑排序

基础与模板:

有两个KahnDFS两个算法

下面给出Kahn的算法模板

c 复制代码
#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

c 复制代码
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、任务调度算法



c 复制代码
#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. 课程表 - 力扣

这里就是判断是否有环

相关推荐
不正经学生3 小时前
C语言预处理详解:编译器真正动手之前的那些事
c语言·开发语言·算法·面试·bug
门思科技3 小时前
LoRaWAN 设备类别:Class A、B、C 对比与选型指南
c语言·开发语言·php
M78佐菲6 小时前
Linux学习笔记:TCP协议
linux·笔记·学习·tcp/ip·算法
Brilliantwxx6 小时前
【Linux】 进程(9)程序与进程地址空间(基础+进阶+面试题)
linux·运维·服务器·开发语言·c++
不怕犯错,就怕不做6 小时前
git prune 自动删除本地记录中那些远程已经不存在的分支引用
linux·服务器·git
yi.Ist7 小时前
数据定义语言-DDL操作
数据库·学习·mysql·oracle·大海豚
xiaobobo33307 小时前
c语言中for循环条件中定义临时栈变量的作用域
c语言·for循环条件定义栈变量·大括号作用域·独立栈变量
一池秋_8 小时前
arm低配linux设备,桌面应用冷启动提速方法
linux·运维·arm开发
惜离殇8 小时前
从零开始的敲代码生活--Linux应用软件(文件操作基础1)
linux·c语言·文件操作·标准io
潘潘的嵌入式日记10 小时前
I²C 从机接收总被覆盖?双缓冲要在 STOP 时交接
c语言·开发语言·单片机