/* 问题描述: 题目描述: 一个完整的软件项目往往会包含很多由代码和文档组成的源文件。编译器在编译整个项目的时候,可能需要按照依赖关系来依次编译每个源文件。比如,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" */ #include using namespace std; class Solution { public: string compileSeq(string input) { //首先完成有向无环图的构建 //统计图中各节点的个数 并标记头节点为-1 //使用优先队列 按照先小后大的顺序遍历输出节点值 int len = input.size(); /*********构建有向无环图(指向关系)*********/ map> 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 indexcount(len, 0);//统计各节点个数 priority_queue, 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 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; } }; int main(){ Solution OnecompileSeq; string res = OnecompileSeq.compileSeq("1,2,-1,1"); cout << res << endl; return 0; }