08-图9 关键活动 (30 分)

假定一个工程项目由一组子任务构成,子任务之间有的可以并行执行,有的必须在完成了其它一些子任务后才能执行。“任务调度”包括一组子任务、以及每个子任务可以执行所依赖的子任务集。

比如完成一个专业的所有课程学习和毕业设计可以看成一个本科生要完成的一项工程,各门课程可以看成是子任务。有些课程可以同时开设,比如英语和C程序设计,它们没有必须先修哪门的约束;有些课程则不可以同时开设,因为它们有先后的依赖关系,比如C程序设计和数据结构两门课,必须先学习前者。

但是需要注意的是,对一组子任务,并不是任意的任务调度都是一个可行的方案。比如方案中存在“子任务A依赖于子任务B,子任务B依赖于子任务C,子任务C又依赖于子任务A”,那么这三个任务哪个都不能先执行,这就是一个不可行的方案。

任务调度问题中,如果还给出了完成每个子任务需要的时间,则我们可以算出完成整个工程需要的最短时间。在这些子任务中,有些任务即使推迟几天完成,也不会影响全局的工期;但是有些任务必须准时完成,否则整个项目的工期就要因此延误,这种任务就叫“关键活动”。

请编写程序判定一个给定的工程项目的任务调度是否可行;如果该调度方案可行,则计算完成整个工程项目需要的最短时间,并输出所有的关键活动。

输入格式:

输入第1行给出两个正整数N(≤)和M,其中N是任务交接点(即衔接相互依赖的两个子任务的节点,例如:若任务2要在任务1完成后才开始,则两任务之间必有一个交接点)的数量。交接点按1~N编号,M是子任务的数量,依次编号为1~M。随后M行,每行给出了3个正整数,分别是该任务开始和完成涉及的交接点编号以及该任务所需的时间,整数间用空格分隔。

输出格式:

如果任务调度不可行,则输出0;否则第1行输出完成整个工程项目需要的时间,第2行开始输出所有关键活动,每个关键活动占一行,按格式“V->W”输出,其中V和W为该任务开始和完成涉及的交接点编号。关键活动输出的顺序规则是:任务开始的交接点编号小者优先,起点编号相同时,与输入时任务的顺序相反。

输入样例:

7 8
1 2 4
1 3 3
2 4 5
3 4 3
4 5 1
4 6 6
5 7 5
6 7 2

输出样例:

17
1->2
2->4
4->6
6->7

  1 #include <stdlib.h>
  2 #include <cstdio>
  3 #include <queue>
  4 #define MaxVertexNum 102
  5 #define INFINITY 65536
  6 using namespace std;
  7 
  8 typedef int Vertex;
  9 typedef int WeightType;
 10 typedef int DataType;
 11 
 12 int Earliest[MaxVertexNum];
 13 int Latest[MaxVertexNum];
 14 int KeyEdge[MaxVertexNum][MaxVertexNum];
 15 
 16 
 17 typedef struct ENode *Edge;
 18 struct ENode{
 19     Vertex V1, V2;
 20     WeightType Weight;
 21 };
 22 
 23 typedef struct AdjVNode *PtrToAdjVNode;
 24 struct AdjVNode{
 25     Vertex AdjV;
 26     WeightType Weight;
 27     PtrToAdjVNode Next;
 28     int flag;
 29 };
 30 
 31 typedef struct Vnode{
 32     PtrToAdjVNode FirstEdge;
 33     
 34 } AdjList[MaxVertexNum];    /* AdjListÊÇÁÚ½Ó±íÀàÐÍ */
 35 
 36 
 37 typedef struct GNode *LGraph;
 38 struct GNode{
 39     int Nv;
 40     int Ne;
 41     AdjList G;
 42     WeightType Matrix[MaxVertexNum][MaxVertexNum];
 43 };
 44 
 45 
 46 LGraph CreateGraph( int VertexNum );
 47 void InsertEdge( LGraph Graph, Edge E );
 48 LGraph BuildGraph();
 49 
 50 bool topSort(LGraph Graph);
 51 int findEarliest(LGraph Graph);
 52 
 53 void bottomSort(LGraph Graph, int EarilestTime);
 54 void outPut(LGraph Graph, int DDL);
 55 
 56 
 57 int main() {
 58     LGraph Graph = BuildGraph();
 59     
 60     if( !topSort(Graph) ) printf("0\n");
 61     else {
 62         int DDL = findEarliest(Graph);
 63         
 64         bottomSort(Graph, DDL);
 65         
 66         
 67         
 68         outPut(Graph, DDL);
 69     }
 70     
 71     
 72     
 73 }
 74 
 75 
 76 LGraph CreateGraph( int VertexNum )
 77 {
 78     Vertex V, W;
 79     LGraph Graph;
 80     
 81     Graph = (LGraph)malloc( sizeof(struct GNode) );
 82     Graph->Nv = VertexNum;
 83     Graph->Ne = 0;
 84     
 85     for (V=0; V<Graph->Nv; V++)
 86         Graph->G[V].FirstEdge = NULL;
 87     
 88     for (V = 0; V<Graph->Nv; V++){
 89         for (W = 0; W<Graph->Nv; W++) {
 90             Graph->Matrix[V][W] = INFINITY;
 91             KeyEdge[V][W] = 1;
 92         }
 93     }
 94     return Graph;
 95 }
 96 void InsertEdge( LGraph Graph, Edge E )
 97 {
 98     PtrToAdjVNode newNode = new AdjVNode;
 99     newNode->Weight = E->Weight;
100     newNode->AdjV = E->V2;
101     
102     newNode->Next = Graph->G[E->V1].FirstEdge;
103     Graph->G[E->V1].FirstEdge = newNode;
104     
105 }
106 LGraph BuildGraph()
107 {
108     LGraph Graph;
109     int Nv;
110     Edge E;
111     Vertex V;
112     
113     scanf("%d", &Nv);
114     Graph = CreateGraph(Nv);
115     
116     scanf("%d", &(Graph->Ne));
117     
118     if(Graph->Ne) {
119         E = new ENode;
120         for(int i=0; i<Graph->Ne; i++) {
121             scanf("%d %d %d", &(E->V1), &(E->V2), &(E->Weight));
122             E->V1--; E->V2--;
123             Graph->Matrix[E->V2][E->V1] = E->Weight;
124             InsertEdge(Graph, E);
125         }
126     }
127     
128     
129     return Graph;
130     
131 }
132 
133 bool topSort(LGraph Graph)
134 {
135     int cnt;
136     int Indegree[MaxVertexNum];
137     Vertex V;
138     queue<Vertex> Q;
139     
140     cnt = 0;
141     for( V=0; V<Graph->Nv; V++) {Indegree[V] = 0; Earliest[V] = 0; }
142     
143     for( V = 0; V < Graph->Nv; V++) {
144         for(PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W=W->Next) {
145             Indegree[W->AdjV]++;
146             
147         }
148     }
149     for(V=0; V<Graph->Nv; V++) if(Indegree[V] == 0) Q.push(V);
150     
151     while(!Q.empty()) {
152         V = Q.front();
153         Q.pop();
154         cnt++;
155         
156         for(PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W=W->Next) {
157             if(--Indegree[W->AdjV] == 0) Q.push(W->AdjV);
158             if(Earliest[W->AdjV] < W->Weight + Earliest[V])
159             {
160                 Earliest[W->AdjV] = W->Weight + Earliest[V];
161                 
162             }
163             
164         }
165         
166         
167     }
168     
169     if(cnt != Graph->Nv) return false;
170     return true;
171     
172     
173 }
174 int findEarliest(LGraph Graph)
175 {
176     
177     Vertex V, MaxV;
178     int compTime;
179     compTime = Earliest[0];
180     
181     for(V = 1; V < Graph->Nv; V++) {
182         if(Earliest[V] > compTime) {compTime = Earliest[V]; MaxV = V; }
183     }
184     
185     return compTime;
186     
187     
188     
189 }
190 void bottomSort(LGraph Graph, int earlyTime)
191 {
192     int OutDegree2[MaxVertexNum];
193     int cnt;
194     Vertex V;
195     queue<Vertex> Q;
196     
197     cnt = 0;
198     
199     for (V = 0; V < Graph->Nv; V++) {
200         OutDegree2[V] = 0;
201         Latest[V] = INFINITY;
202     }
203     
204     for( V = 0; V < Graph->Nv; V++) {
205         for(PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W=W->Next) {
206             OutDegree2[V]++;
207         }
208         if (!OutDegree2[V]) {
209             Latest[V] = earlyTime;
210         }
211     }
212     
213     for(V=0; V<Graph->Nv; V++) if(OutDegree2[V] == 0) Q.push(V);
214     
215     while(!Q.empty()) {
216         
217         V = Q.front();
218         Q.pop();
219         cnt++;
220        
221         for (Vertex W = 0; W<Graph->Nv; W++) {
222             
223             if(Graph->Matrix[V][W] != INFINITY) {
224                 if (--OutDegree2[W] == 0) {
225                     Q.push(W);
226                 }
227                 
228                 if (Latest[V] - Graph->Matrix[V][W] < Latest[W]) {
229                     Latest[W] = Latest[V] - Graph->Matrix[V][W];
230                 }
231                 
232             }
233             
234         }
235         
236         
237         
238     }
239     for (Vertex V = 0; V<Graph->Nv; V++) {
240         for (Vertex W = 0; W < Graph->Nv; W++) {
241             KeyEdge[V][W] = Latest[W] - Earliest[V] - Graph->Matrix[W][V];
242         }
243     }
244     
245   
246     
247 }
248 void outPut(LGraph Graph, int DDL)
249 {
250     printf("%d\n", DDL);
251     for (Vertex V = 0; V<Graph->Nv; V++) {
252         for (PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W=W->Next) {
253             if (KeyEdge[V][W->AdjV] == 0) {
254                 printf("%d->%d\n", V+1, W->AdjV+1);
255             }
256         }
257     }
258 }

 

posted @ 2019-05-28 10:37  Acoccus  阅读(173)  评论(0编辑  收藏  举报