赞
踩
一个无环的有向图称做有向无环图(Directed Acyclic Graph)。简称DAG 图。
在图论中,如果一个有向图无法从某个顶点出发经过若干条边回到该点,则这个图是一个有向无环图(DAG图)。
因为有向图中一个点经过两种路线到达另一个点未必形成环,因此有向无环图未必能转化成树,但任何有向树均为有向无环图。
使用有向无环图解题时,要先判断是否是有向无环题。如果任务x必须在任务y之前完成:x→y,而y→z。也就是说一般在涉及优先级限制的问题时,使用有向无环图的方法。
注意与并查集进行区分。
关于并查集模板:https://blog.csdn.net/qq_41687938/article/details/112850265
做有向无环图题的时候,一共就三步:
1.根据题目意思及输入,理清两节点间的指向关系,构建由前指向后的有向无环图。
也就是构建一个map,key为当前节点,val数组为当前节点指向的那些节点。
2.根据有向无环图,统计每个节点出现的次数,因为有的节点已经出现过,但还是可能由其他指向路径的节点再指回来,在输出的时候需要遍历其最后出现的地方,所以要记一下它出现的次数。
其中,头节点的次数记为-1,并将头节点保存起来,方便接下来的遍历。
3.因为有向无环图的输出一般都有要求按大小关系输出(本文按升序输出!),也就是构建一个优先队列来完成节点输出。每遍历一个节点就将其所指向的节点压入队列中,实现了某节点的下一层与当前节点层的其他节点的比较。并将遍历到的节点输出。直到队列中所有节点输出。
一个完整的软件项目往往会包含很多由代码和文档组成的源文件。编译器在编译整个项目的时候,可能需要按照依赖关系来依次编译每个源文件。比如,A.cpp 依赖 B.cpp,那么在编译的时候,编译器需要先编译 B.cpp,才能再编译 A.cpp。 假设现有 0,1,2,3 四个文件,0号文件依赖1号文件,1号文件依赖2号文件,3号文件依赖1号文件,则源文件的编译顺序为 2,1,0,3 或 2,1,3,0。现给出文件依赖关系,如 1,2,-1,1,表示0号文件依赖1号文件,1号文件依赖2号文件,2号文件没有依赖,3号文件依赖1号文件。请补充完整程序,返回正确的编译顺序。注意如有同时可以编译多个文件的情况,按数字升序返回一种情况即可,比如前述案例输出为:2,1,0,3
输入例子1:
"1,2,-1,1"
输出例子1:
"2,1,0,3"
- class Solution {
- public:
- string compileSeq(string input) {
- //首先完成有向无环图的构建
- //统计图中各节点的个数 并标记头节点为-1
- //使用优先队列 按照先小后大的顺序遍历输出节点值
-
- int len = input.size();
-
- /*********构建有向无环图(指向关系)*********/
- map<int, vector<int>> mp;//first为先 second为后, 也就是second依赖于first
- string tmp;
- int idx = 0;
- for(auto& s:input){
- if(s != ',')
- tmp += s;
- else{
- mp[stoi(tmp)].push_back(idx++);
- string().swap(tmp);//清空string
- }
- }
- if(!tmp.empty())
- mp[stoi(tmp)].push_back(idx++);
-
- /**********统计各节点个数 并保存头节点***********/
- vector<int> indexcount(len, 0);//统计各节点个数
- priority_queue<int, vector<int>, greater<>> pq;//保存节点
- for(auto& m:mp){
- if(m.first == -1){
- for(auto& a:m.second){
- pq.push(a);
- indexcount[a] = -1;
- }
- }else{
- for(auto& a:m.second)
- ++indexcount[a];
- }
- }
-
- /************根据指向关系遍历图 并按照优先队列输出结果********/
- vector<int> ans;
- while(!pq.empty()){
- int node = pq.top();
- pq.pop();//输出了就需要从优先队列中弹出
- ans.push_back(node);
- for(auto& m:mp[node]){
- if(--indexcount[m] == 0)//如果该节点是最后一次在图中出现 则放入队列中
- pq.push(m);
- }
- }
-
- /***********输出结果************/
- string res;
- for(auto& i:ans){
- res += to_string(i);
- res.push_back(',');
- }
- if(!res.empty())
- res.pop_back();
-
- return res;
- }
- };

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。