任务调度

题目http://www.itint5.com/oj/#10

有n个任务需要完成(编号1到n),任务之间有一些依赖关系,如果任务a依赖于任务b和c,那么只有当任务b和任务c完成之后才能完成任务a。给定所有的依赖关系,判断这些任务是否能够完成。如果能够完成,请给出一个合法的任务完成序列。

样例:
n=5
1->2,3
3->4

上述样例中任务1依赖于任务2和任务3,任务3依赖于任务4,那么存在合法的任务完成序列4,3,2,1,5

这道题是拓扑排序的应用。

http://baike.baidu.com/view/288212.htm

http://www.geeksforgeeks.org/topological-sorting/

拓扑排序方法如下:
(1)从有向图中选择一个没有前驱(即入度为0)的顶点并且输出它.
(2)从网中删去该顶点,并且删去从该顶点发出的全部有向边.
(3)重复上述两步,直到剩余的网中不再存在没有前趋的顶点为止.

 1 typedef int JobID;
 2 
 3 /*
 4  * deps[id]表示任务id所依赖的任务
 5  * 如果存在合法的任务完成序列,返回true,否则返回false
 6  * 合法的任务序列请存放在参数result中(已经分配空间,不需要push_back)
 7  */
 8 bool jobSchedule(const map<JobID, vector<JobID> > &deps, int n,
 9                                    vector<JobID> &result) {
10     
11     vector<JobID> indegree(n+1, 0); // 计算图形入度
12     map<JobID, vector<JobID> > rmap;
13     map<JobID, vector<JobID> >::const_iterator it = deps.begin();
14     for(; it != deps.end(); it++) {
15         indegree[it->first] = it->second.size();
16         for(int i = 0; i < it->second.size(); i++) {
17             rmap[it->second[i]].push_back(it->first);
18         }
19     }
20     
21     stack<JobID> s;
22     for(int i = 1; i <= n; i++) {
23         if(indegree[i] == 0) {
24             s.push(i);
25         }
26     }
27     
28     for(int i = 0; i < n; i++) {
29         if(s.empty()) return false; // not finish schedule
30         JobID id = s.top(); 
31         s.pop();
32         result[i] = id;
33         for(int j = 0; j < rmap[id].size(); j++) {
34             indegree[rmap[id][j]]--;
35             if(indegree[rmap[id][j]] == 0) {
36                 s.push(rmap[id][j]);
37             }
38         }
39     }
40     return true;
41 }

解题思路:

1. 参考拓扑排序算法

2. stack为空(没有前驱的顶点不存在)时,图中仍然存在顶点,表示任务调度失败。

原文地址:https://www.cnblogs.com/zhengjiankang/p/3872008.html