PTA数据结构与算法题目集(中文) 7-11

PTA数据结构与算法题目集(中文)  7-11

7-11 关键活动 (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
题目分析:拓扑排序的基本应用 这是拓扑排序中的关键路径问题 对于拓扑排序是要利用的每个节点的入度来进行入队 关键路径是在这基础上 在每次入队之前先计算其邻接点的Earliest(用其它名称也可以) 而从末尾开始计算Latest时 要从达到最大时间的那个节点开始 该节点的Latest等于Earliest
对于从末尾开始时 要利用出度来进行入队
  1 #define _CRT_SECURE_NO_WARNINGS   
  2 #include<stdio.h>
  3 #include<stdlib.h>
  4 #include<malloc.h>
  5 #define MAXVERTEXNUM 110
  6 #define INIFITY 65535
  7 
  8 typedef struct ENode* Edge;
  9 struct ENode
 10 {
 11     int V1, V2;
 12     int Weight;
 13 };
 14 
 15 typedef struct AdvjNode* PtrToAdvjNode;
 16 struct AdvjNode
 17 {
 18     int Advj;
 19     int Weight;
 20     PtrToAdvjNode Next;
 21 };
 22 
 23 typedef struct VNode
 24 {
 25     PtrToAdvjNode FirstNode;
 26     PtrToAdvjNode LastNode;
 27     int InDegree;
 28     int OutDegree;
 29 }AdjList[MAXVERTEXNUM];
 30 
 31 typedef struct GNode* Graph;
 32 struct GNode
 33 {
 34     int Nv;
 35     int Ne;
 36     AdjList G;
 37 };
 38 
 39 Graph BuildGraph(int VertexNum)
 40 {
 41     Graph Gra = (Graph)malloc(sizeof(struct GNode));
 42     Gra->Nv = VertexNum;
 43     Gra->Ne = 0;
 44     for (int i =1; i <=Gra->Nv; i++)
 45     {
 46         Gra->G[i].FirstNode = NULL;
 47         Gra->G[i].LastNode = NULL;
 48         Gra->G[i].OutDegree = 0;
 49         Gra->G[i].InDegree = 0;
 50     }
 51     return Gra;
 52 }
 53 
 54 void Insert(Edge E, Graph Gra)
 55 {
 56     PtrToAdvjNode NewNode = (PtrToAdvjNode)malloc(sizeof(struct AdvjNode));
 57     NewNode->Advj = E->V2;
 58     NewNode->Weight = E->Weight;
 59     NewNode->Next = Gra->G[E->V1].FirstNode;
 60     Gra->G[E->V1].FirstNode = NewNode;
 61     Gra->G[E->V2].InDegree++;
 62 
 63     NewNode = (PtrToAdvjNode)malloc(sizeof(struct AdvjNode));
 64     NewNode->Advj = E->V1;
 65     NewNode->Weight = E->Weight;
 66     NewNode->Next = Gra->G[E->V2].LastNode;
 67     Gra->G[E->V2].LastNode = NewNode;
 68     Gra->G[E->V1].OutDegree++;
 69 }
 70 
 71 Graph CreateGraph()
 72 {
 73     Edge E = (Edge)malloc(sizeof(struct ENode));
 74     int N, M;
 75     scanf("%d%d", &N, &M);
 76     Graph Gra = BuildGraph(N);
 77     Gra->Ne = M;
 78     for (int i = 0; i < Gra->Ne; i++)
 79     {
 80         scanf("%d%d%d", &(E->V1), &(E->V2), &(E->Weight));
 81         Insert(E, Gra);
 82     }
 83     return Gra;
 84 }
 85 
 86 int Queue[MAXVERTEXNUM];
 87 int Rear = 0;
 88 int Front = 1;
 89 int Size = 0;
 90 int IsEmpty()
 91 {
 92     return Size == 0;
 93 }
 94 int Succ(int num)
 95 {
 96     if (num < MAXVERTEXNUM)
 97         return num;
 98     else
 99         return 0;
100 }
101 
102 void EnQueue(int V)
103 {
104     Rear = Succ(Rear + 1);
105     Queue[Rear] = V;
106     Size++;
107 }
108 
109 int DeQueue()
110 {
111     int num = Queue[Front];
112     Front = Succ(Front + 1);
113     Size--;
114     return num;
115 }
116 
117 void Initilize()
118 {
119     Rear = 0;
120     Front = 1;
121     Size = 0;
122 }
123 
124 int Earliest[MAXVERTEXNUM];
125 int Latest[MAXVERTEXNUM];
126 int TopOrder[MAXVERTEXNUM];
127 int InDegree[MAXVERTEXNUM];
128 int OutDegree[MAXVERTEXNUM];
129 int S;
130 int TopSort(Graph Gra)
131 {
132     int cnt = 0;
133     for (int i = 1; i <= Gra->Nv; i++)
134     {
135         Earliest[i] = 0;
136         Latest[i] = INIFITY;
137     }
138     for (int i = 1; i <=Gra->Nv; i++)
139         for (PtrToAdvjNode W = Gra->G[i].FirstNode; W; W = W->Next)
140             InDegree[W->Advj]++;
141     for (int i =1; i <=Gra->Nv; i++)
142     {
143         if (!InDegree[i])
144         {
145             EnQueue(i);
146             Earliest[i] = 0;
147         }
148     }
149     while (!IsEmpty())
150     {
151         int V = DeQueue();
152         TopOrder[S++] = V;
153         cnt++;
154         for (PtrToAdvjNode W = Gra->G[V].FirstNode; W; W = W->Next)
155         {
156             if (Earliest[V] + W->Weight > Earliest[W->Advj])
157                 Earliest[W->Advj] = Earliest[V] + W->Weight;
158             if (--InDegree[W->Advj] == 0)
159                 EnQueue(W->Advj);
160         }
161     }
162 
163     //从最后结束的任务开始
164     int Max = -1;
165     int V;
166     for (int i = 1; i <= Gra->Nv; i++)
167     {
168         if (Earliest[i] > Max)
169         {
170             Max = Earliest[i];
171             V = i;
172         }
173     }
174 
175     Initilize();
176     Latest[V] = Max;
177     for (int i = 1; i <= Gra->Nv; i++)
178         for (PtrToAdvjNode W = Gra->G[i].LastNode; W; W = W->Next)
179             OutDegree[W->Advj]++;
180     for (int i = 1; i <= Gra->Nv; i++)
181         if (!OutDegree[i])
182             EnQueue(i);
183     while (!IsEmpty())
184     {
185         int V = DeQueue();
186         for (PtrToAdvjNode W = Gra->G[V].LastNode; W; W = W->Next)
187         {
188             if (Latest[V] - W->Weight < Latest[W->Advj])
189                 Latest[W->Advj] = Latest[V] - W->Weight;
190             if (--OutDegree[W->Advj] == 0)
191                 EnQueue(W->Advj);
192         }
193     }
194 
195     Initilize();
196     for(int i=1;i<Gra->Nv;i++)
197         for (PtrToAdvjNode W = Gra->G[i].FirstNode; W; W = W->Next)
198         {
199             if (Latest[W->Advj] - Earliest[i] - W->Weight == 0)
200             {
201                 EnQueue(i);
202                 EnQueue(W->Advj);
203             }
204         }
205     if (cnt == Gra->Nv)
206         return Max;
207     else
208         return 0;
209 }
210 
211 int main()
212 {
213     Graph G = CreateGraph();
214     int sum;
215     if ((sum=TopSort(G)))
216     {
217         printf("%d\n",sum);
218         while (Size)
219         {
220             printf("%d->", DeQueue());
221             printf("%d\n", DeQueue());
222         }
223     }
224     else
225         printf("0");
226     return 0;
227 }
View Code

 

posted @ 2019-09-27 18:48  57one  阅读(476)  评论(0编辑  收藏  举报