BFS、DFS与选课问题(拓扑排序)
1选课问题
Leetcode上有这样一道题:有代号0,1,2……n-1的n门课程。其中选择某些课程需要另一些课程作为前提条件。用一组pair来表示这些条件:[1,0],[1,2],表示如果要选修课程1,必须先选修课程0和课程2。问是否可能把这n门课程都选修一遍。
这个问题看起来相当复杂。难点在于,一门课程可能需要多门课程作为前提条件,这样就很难找到一条可以不重复地遍历所有课程的方法。
比较笨的方法就是先找出那些不需要前提条件的课程,然后由他们出发将那些只需要他们作为前提条件的课程修完。再循环往复。一直到某一次遍历之后,并没有修到新的课程。最后再检查是否还有课程没能修够。这样的话,最坏情况,我们是时间复杂度最坏能达到O(N^3)。使用了unordered_multimap作为辅助工具,代码被Accept了。但是运行时间是最好的coder的10倍。于是,细细研究他人的算法。
2 BFS
其实。这道题难在用一维数据结构来表示这些前提条件,很容易增大时间复杂度。于是,考虑用二维数据结构来表示。
图!而题中给的条件明显是一对多的。那么,适合用邻接链表法表示。采用数据结构vector<unordered_set<int>> map来表示。vector的每个元素表示由某门课程作为前提条件的一组课程。每门课程需要的前提条件可以用一组向量表示vector<int> de。我们用入度称呼这个值,也就是说在图中,进入该节点有多少条路径。那么对于那些不需要前提条件就完成的课程,其入度为0。
BFS法,广度优先。我们先找到一门入度为0的课,然后由它作为前提条件的课程的入度都可以减1,因为这门课程学到了,就等于不需要这个前提条件了。而以它为前提的课程就是该节点的邻接节点。用这种方法,我们每次学到一门课程,N次就可以学完所有的课程,如果某一次没有学到新的课程,那么最终肯定是无法学完的。
上代码:
class Solution {
public:
bool canFinish(int n, vector<pair<int, int>>& pre) {
vector<unordered_set<int> > gra(n);
vector<int> de(n,);
//make graph
for(auto a:pre)
{
gra[a.second].insert(a.first);
}
//calculate the indegree
for(int i=;i<n;++i)
{
for(auto a:gra[i])
de[a]++;
}
for(int i=;i<n;++i)
{
int j=;
for(;j<n;++j)
{
if(de[j]==) break;
}
if(j==n) return ; //this time could not learn a new lesson and we won't make it
de[j]=-; //in case next time we will learn this lesson again
for(auto a:gra[j])
de[a]--; //any lesson take this lesson as it's prerequisites, it's indegree decrease 1
}
return ;
}
};
3 DFS
那么DFS(深度优先搜索)是怎么样的思路呢?其实,如果这个图中存在一个环的话,那么肯定无法完成任务。那么什么情况下会完不成任务呢?也就是说1->2,2->3,3->1,也就是说形成了一个环。所以我们把原问题转化为检测图中是否有环。检测环的方法?从某个节点出发,如果又回到该节点,那么此图有环!
我们依次从任意节点出发,遍历该节点可以到达的所有节点,我们用一个向量vector<bool> onePath来记录从该节点出发经过的节点。为了防止重复,我们用变量vector<bool> path记录所有遍历过的节点。
上代码:
class Solution {
public:
bool canFinish(int n, vector<pair<int, int>>& pre) {
vector<unordered_set<int> > gra(n);
vector<bool> path(n,),onePath(n,);
//make graph
for(auto a:pre)
{
gra[a.second].insert(a.first);
}
for(int i=;i<n;++i)
{
if(path[i]) continue;
if(dfs_circle(gra,i,path,onePath))
return ;
}
return ;
}
bool dfs_circle(vector<unordered_set<int> >& gra,int node,vector<bool>& path,vector<bool>& onePath)
{
if(onePath[node]==) return true;
path[node]=onePath[node]=;
for(auto a:gra[node])
if(dfs_circle(gra,a,path,onePath))
return ;
onePath[node]=;
return ;
}
};
这种转化问题的解法真得很巧妙!太赞!
另外,对于很多条件有交叉的题目,就考虑用图论方法解决,尤其是DFS和BFS算法。
BFS、DFS与选课问题(拓扑排序)的更多相关文章
- bfs+dfs乱搞+类似拓扑排序——cf1182D
代码不知道上了多少补丁..终于过了 用类似拓扑排序的办法收缩整棵树得到x,然后找到x直连的最远的和最近的点 只有这三个点可能是根,依次判一下即可 另外题解的第一种方法时找直径,然后判两端点+重心+所有 ...
- 强大的dfs(用处1——拓扑排序【xdoj1025】,用处二——求强联通分量【ccf高速公路】)当然dfs用处多着咧
xdoj 1025 亮亮最近在玩一款叫做“梦想庄园”的经营游戏.在游戏中,你可以耕种,养羊甚至建造纺织厂. 如果你需要制造衣服,你首先得有布匹和毛线.布匹由棉花纺织而成:毛线由羊毛制成,而羊需要饲料才 ...
- Ordering Tasks(拓扑排序+dfs)
Ordering Tasks John has n tasks to do. Unfortunately, the tasks are not independent and the executio ...
- 拓扑排序入门详解&&Educational Codeforces Round 72 (Rated for Div. 2)-----D
https://codeforces.com/contest/1217 D:给定一个有向图,给图染色,使图中的环不只由一种颜色构成,输出每一条边的颜色 不成环的边全部用1染色 ps:最后输出需要注意, ...
- 图论相关知识(DFS、BFS、拓扑排序、最小代价生成树、最短路径)
图的存储 假设是n点m边的图: 邻接矩阵:很简单,但是遍历图的时间复杂度和空间复杂度都为n^2,不适合数据量大的情况 邻接表:略微复杂一丢丢,空间复杂度n+m,遍历图的时间复杂度为m,适用情况更广 前 ...
- BFS (1)算法模板 看是否需要分层 (2)拓扑排序——检测编译时的循环依赖 制定有依赖关系的任务的执行顺序 djkstra无非是将bfs模板中的deque修改为heapq
BFS模板,记住这5个: (1)针对树的BFS 1.1 无需分层遍历 from collections import deque def levelOrderTree(root): if not ro ...
- hdu1532 用BFS求拓扑排序
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1285 题目给出一些点对之间的先后顺序,要求给出一个字典序最小的拓扑排列.对于拓扑排序的问题,我们有DF ...
- 拓扑排序详解(梅开二度之dfs版按字典序输出拓扑路径+dfs版输出全部拓扑路径
什么是拓扑排序? 先穿袜子再穿鞋,先当孙子再当爷.这就是拓扑排序! 拓扑排序说白了其实不太算是一种排序算法,但又像是一种排序(我是不是说了个废话qwq) 他其实是一个有向无环图(DAG, Direct ...
- ACM/ICPC 之 拓扑排序+DFS(POJ1128(ZOJ1083)-POJ1270)
两道经典的同类型拓扑排序+DFS问题,第二题较第一题简单,其中的难点在于字典序输出+建立单向无环图,另外理解题意是最难的难点,没有之一... POJ1128(ZOJ1083)-Frame Stacki ...
- 百度之星热身赛-1001(dfs拓扑排序)
题意:作为年度优秀魔法学员的奖赏,哈利得到了一台具有魔力的计算机.这台计算机一旦开始处理某个任务,就会一直处理到这个任务结束为止(所以你可以认为它是单线程的).有一天,这台计算机得到了n个任务要处理, ...
随机推荐
- ios开发入门资料整理
说到 iOS 开发,自己学得也很浅.不过至少独立一人完成了一个应用的开发到 App Store 上线整个过程.既然有人让我说些推荐和建议,就分享一下. 首先建议阅读 Start Developing ...
- 如何将CKeditor编辑器的上传和thinkphp结合
转载:THINKPHP代码中 lxepoo的文章 有时候我们会发现,我们需要对上传文件进行日志记录,这样的记录通常写在LOG文件或数据库中,那么,通过TP本身的上传类,可以实现的,但是只能做到编辑器外 ...
- FPGA中的delay与latency
delay和latency都有延迟的意义,在FPGA中二者又有具体的区别. latency出现在时序逻辑电路中,表示数据从输入到输出有效经过的时间,通常以时钟周期为单位. delay出现在组合逻辑电路 ...
- 标签栏使用Demo二
// // PHTagViewFrame.m // 标签的使用二 // // Created by 123 on 16/9/6. // Copyright © 2016年 彭洪. All ri ...
- 把复杂json解析成javabean
工具:fastjson1.2.9 用其他工具也行,比如json-lib.gson 用法都差不多 先来一段json { "page": { "pagenow": ...
- Jsp九大内置对象及其作用域
本文主要介绍Jsp九大内置对象及其作用域,着重介绍几个常用的,希望对初学者有所帮助. 1 Jsp九大内置对象 2 详细介绍 2.1 request javax.servlet.http.HttpSer ...
- CSS3与页面布局学习笔记(二)——盒子模型(Box Model)、边距折叠、内联与块标签、CSSReset
一.盒子模型(Box Model) 盒子模型也有人称为框模型,HTML中的多数元素都会在浏览器中生成一个矩形的区域,每个区域包含四个组成部分,从外向内依次是:外边距(Margin).边框(Border ...
- 基于RulesEngine的业务规则实现
规则引擎由推理引擎发展而来,是一种嵌入在应用程序中的组件,实现了将业务决策从应用程序代码中分离出来,并使用预定义的语义模块编写业务决策.接受数据输入,解释业务规则,并根据业务规则做出业务决策.比较常见 ...
- 网站开发中很实用的 HTML5 & jQuery 插件
这篇文章挑选了15款在网站开发中很实用的 HTML5 & jQuery 插件,如果你正在寻找能优化网站,使其更具创造力和视觉冲击,那么本文正是你需要的.这些优秀的 jQuery 插件能为你的网 ...
- asp.net保存网上图片到服务器
本文讲述的是根据一个图片的url地址,保存图片到asp.net服务器端的实现方法. 可以先了解这篇文章http://keleyi.com/a/bjac/0899dpgi.htm,以更好的理解本文. 首 ...