题目:
学校要上课,顺序有先后。
能否排排课,把课都上完。
输入: prerequisites = {{1}, {3}, {3}, {}}
解释: 一共有四门课,编号分别为0、1、2、3,
第0门课需要先完成第1门课,
第1门课需要先完成第3门课,
第2门课需要先完成第3门课,
第3门课没有要求。
输出:true
解释: 一个可行的上课顺序是3、2、1、0
题目分析:是一个有向无环图的拓扑排序问题。
代码实现:
#include<iostream>
#include<vector>
#include<list>
#include<queue>
using namespace std;
bool ScheduleCourses(vector<vector<int> >& prerequisites)
{
vector<int> degree(prerequisites.size()); //每个节点的入度
vector<list<int> > neighbors(prerequisites.size()); //每个节点的后继节点
queue<int> available; //当前可以上的课节点(入度为0)
for (int i = 0; i < prerequisites.size(); ++i) {
degree[i] = prerequisites[i].size();
if (degree[i] == 0)
available.push(i);
}
for (int to = 0; to < prerequisites.size(); ++to) {
for (int from : prerequisites[to]) {
neighbors[from].push_back(to);
}
}
int ct = 0; //记录删除节点数目
while (available.size()) {
cout << available.front() << endl;
for (int id : neighbors[available.front()]) {
--degree[id]; //将该节点后继节点入度-1
if (degree[id] == 0)
available.push(id);
}
available.pop();
++ct;
}
return ct == prerequisites.size();
}
int main()
{
vector<vector<int> > prerequisites({ {1},{3},{3},{} });
if (ScheduleCourses(prerequisites))
cout << "true" << endl;
else
cout << "false" << endl;
return 0;
}
总结:贪心策略:degree = 0。
箴言录
出淤泥而不染,濯清涟而不妖。