当前位置: 首页 > ai >正文

【LeetCode 207】课程表(有向无环图 DAG、拓扑排序)

题面:

在这里插入图片描述
Link:LeetCode 207 课程表

思路:

首先很容易想到如果图中存在有向环,则表示这个环里的课是没法学习的(因为环里的课都在等待自己的前置课被学习)。
例如: 0 → 1 → 2 → 0 0\rightarrow1\rightarrow2\rightarrow0 0120

简单用拓扑排序的思想解释一下:容易想到只有 入度为 0 的顶点(课)是可以一开始就直接学习的。如果有顶点 u u u 被遍历了( u u u 课程被学习了),其指向的所有邻接点的入度就可以减一(邻接点的前置课 u u u 已经学习了,因此 u u u 对它们已经没有约束了)。

因此,只有 有向无环图(DAG) 才是合法的。
有个性质:能拓扑排序的图一定是有向无环图(DAG),有向无环图一定能拓扑排序。

DAG的判断一般就两种方法:

  1. 用入度搞个拓扑排序
  2. 可以直接 DFS 判断是否存在 有向环,对图进行一遍 DFS,在得到的 DFS 树上看看有没有连向祖先的非树边(返祖边)。如果有的话,那就有环了。简单来说,直接判断 DFS 的搜索过程中是否有结点被二次遍历了,有就是出现环了。

代码:

拓扑排序:

bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {vector<int> d(numCourses, 0);vector<vector<int>> edges(numCourses);for(const auto& edge : prerequisites) {edges[edge[1]].emplace_back(edge[0]);++ d[edge[0]];}int visited = 0;queue<int> q;for(int i = 0; i < numCourses; ++i)if(!d[i])q.push(i);while(!q.empty()) {++visited;int u = q.front(); q.pop();for(const auto& v : edges[u]) {--d[v];if(!d[v]) q.push(v);}}return visited == numCourses;
}

DFS判断环:

class Solution {
private:vector<vector<int>> edges;vector<int> visited;bool valid = true;public:void dfs(int u) {visited[u]=true;if(!valid) return ;for(const auto &v : edges[u]) {if(visited[v] == 1) {valid = false;return ;}if(valid && !visited[v]) dfs(v);}visited[u]++;return ;}bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {edges.resize(numCourses, vector<int>());visited.resize(numCourses, false);for(const auto &edge : prerequisites) edges[edge[1]].emplace_back(edge[0]);for(int i=0;i<numCourses && valid;i++)if(!visited[i])dfs(i);return valid;}
};
http://www.xdnf.cn/news/14412.html

相关文章:

  • 在C++中进程间通信(IPC)
  • 数据库学习(七)——MySQL执行引擎
  • Google机器学习实践指南(非线性特征工程解析)
  • 人工智能学习37-Keras手写识别预测
  • 对于数据库触发器自动执行的理解
  • Java类的继承
  • Luckfox Pico Pi RV1106学习<3>:支持IMX415摄像头
  • BeckHoff <---> Keyence (MD-X)激光 刻印机 Profient 通讯
  • Elasticsearch:什么是混合搜索?
  • AIGC 基础篇 高等数学篇 06 向量代数与空间解析几何
  • 人月神话-学习记录
  • SQL Developer 表复制
  • Python安装与使用教程
  • Maven在依赖管理工具方面的内容
  • Java多线程通信:wait/notify与sleep的深度剖析(时序图详解)
  • Spring是如何实现有代理对象的循环依赖
  • 【SQLAlchemy系列】 SQLAlchemy 中的多条件查询:or*与 in*操作符
  • 智能土木通 - 土木工程专业知识问答系统02-RAG检索模块搭建
  • AC耦合与DC耦合
  • 体验AI智能投资!AI Hedge Fund了解一下
  • Java可变参数方法的常见错误与最佳实践
  • hyper-v虚拟机使用双屏
  • iOS —— UI(2)
  • Spring Cloud 所有组件全面总结
  • 「AI大数据」| 智慧公路大数据运营中心解决方案
  • Java类加载器与双亲委派模型深度解析
  • DNS递归查询
  • BOLL指标
  • Oracle21cR3之客户端安装错误及处理方法
  • 第11章 结构 笔记