16:50:21 2019-09-08

上午交了C++作业 。。感觉自己很菜

 20:42:29  2019-09-10

已经开学了 对于前两章的学习就写在这篇随笔上了  今天终于把困扰我的一道简单题写完了..(os:难受)

 

PTA第23题 利用拓扑排序 计算 关键路径中 最短时间 及 机动时间的问题

注意printf中 参数入栈的顺序

  1 #define _CRT_SECURE_NO_WARNINGS  
  2 #include<stdio.h>
  3 #include<malloc.h>
  4 //图的邻接表表示法
  5 #define MaxVerterNum 110    //最大顶点数
  6 #define INFINITY 65535        //
  7 typedef int Vertex;            //顶点下标表示顶点
  8 typedef int WeightType;        //边的权值
  9 typedef char DataType;        //顶点存储的数据类型
 10 
 11 //边的定义
 12 typedef struct ENode* PtrToENode;
 13 typedef PtrToENode Edge;
 14 struct ENode
 15 {
 16     Vertex V1, V2; //有向边<V1,V2>
 17     WeightType Weight;  //权重
 18 };
 19 
 20 //邻接点的定义
 21 typedef struct AdjVNode* PtrToAdjVNode;
 22 struct AdjVNode
 23 {
 24     Vertex AdjV;  //邻接点下标
 25     WeightType Weight; //边权重
 26     PtrToAdjVNode Next; //指向下一个邻接点的指针  //指向出度或入度的节点 具体视头节点而定
 27 };
 28 
 29 //顶点表头节点的定义
 30 typedef struct Vnode
 31 {
 32     PtrToAdjVNode FirstEdge;  //边表头指针 指向出度
 33     PtrToAdjVNode LastEdge;   //边表头指针 指向入度
 34     DataType Data;            //存顶点的数据
 35 }AdjList[MaxVerterNum];        //AdjList是邻接表类型
 36 
 37 //图节点的定义
 38 typedef struct GNode* PtrToGNode;
 39 typedef PtrToGNode LGraph;
 40 struct GNode
 41 {
 42     int Nv;  //顶点数
 43     int Ne;  //边数
 44     AdjList G;  //邻接表
 45 };
 46 
 47 LGraph CreateGraph(int VertexNum)
 48 {//初始化一个有VertexNum个顶点但没有边的图
 49     Vertex V;
 50     LGraph Graph;
 51 
 52     Graph = (LGraph)malloc(sizeof(struct GNode)); //建立图
 53     Graph->Nv = VertexNum;
 54     Graph->Ne = 0;
 55     //初始化邻接表头指针
 56     for (V = 1; V <= Graph->Nv; V++)
 57     {
 58         Graph->G[V].FirstEdge = NULL;
 59         Graph->G[V].LastEdge = NULL;
 60     }
 61     return Graph;
 62 }
 63 void InsertEdge(LGraph Graph, Edge E)
 64 {
 65     PtrToAdjVNode NewNode;
 66     //插入边<V1,V2>  链接出度
 67     NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
 68     NewNode->AdjV = E->V2;
 69     NewNode->Weight = E->Weight;
 70     NewNode->Next = Graph->G[E->V1].FirstEdge;
 71     Graph->G[E->V1].FirstEdge = NewNode;
 72 
 73     //链接入度
 74     NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
 75     NewNode->AdjV = E->V1;
 76     NewNode->Weight = E->Weight;
 77     NewNode->Next = Graph->G[E->V2].LastEdge;
 78     Graph->G[E->V2].LastEdge = NewNode;
 79     //若是无向图 还要插入边<V2,V1>
 80     /*NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
 81     NewNode->AdjV = E->V1;
 82     NewNode->Weight = E->Weight;
 83     NewNode->Next = Graph->G[E->V2].FirstEdge;
 84     Graph->G[E->V2].FirstEdge = NewNode;*/
 85 }
 86 LGraph BuildGraph()
 87 {
 88     LGraph Graph;
 89     Edge E;
 90     Vertex V;
 91     int Nv, i;
 92 
 93     scanf("%d", &Nv);   /* 读入顶点个数 */
 94     Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */
 95     scanf("%d", &(Graph->Ne));  //读入边数
 96     if (Graph->Ne != 0)
 97     {
 98         E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */
 99         /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */
100         for (i = 1; i <= Graph->Ne; i++)
101         {
102             scanf("%d %d %d", &E->V1, &E->V2, &E->Weight);
103             InsertEdge(Graph, E);
104         }
105     }
106     return Graph;
107 }
108 
109 #define Size 110
110 int Queue[Size];
111 int Front = 1;
112 int Rear = 0;
113 int size = 0;
114 int Succ(int Num)
115 {
116     if (Num < Size)
117         return Num;
118     else
119         return 0;
120 }
121 void EnQueue(int Num)
122 {
123     Rear = Succ(Rear + 1);
124     Queue[Rear] = Num;
125     size++;
126 }
127 int DeQueue()
128 {
129     int Num = Queue[Front];
130     Front = Succ(Front + 1);
131     size--;
132     return Num;
133 }
134 int IsEmpty()
135 {
136     return (size == 0) ? 1 : 0;
137 }
138 void Clear()
139 {
140     for (int i = 0; i < Size; i++)
141         Queue[i] = 0;
142     Front = 1;
143     Rear = 0;
144     size = 0;
145 }
146 //利用邻接表实现拓扑排序
147 int TopOrder[110];  //顺序存储排序后的顶点下标
148 int Earliest[110];
149 int Latest[110];
150 int TopSort(LGraph Graph)
151 {        //对Graph进为拓扑排序 ,TopOrder[] 顺序存储排序后的顶点下标
152     int Indegree[110];
153     int cnt = 0;
154     for (int i = 1; i <= Graph->Nv; i++)    //初始化Indegree
155         Indegree[i] = 0;
156     for (int i = 1; i <= Graph->Nv; i++)
157         for (PtrToAdjVNode W = Graph->G[i].FirstEdge; W; W = W->Next)
158         {
159             Indegree[W->AdjV]++;
160         }
161     for (int i = 1; i <= Graph->Nv; i++)
162         if (Indegree[i] == 0)
163         {
164             EnQueue(i);
165             Earliest[i] = 0;
166         }
167     //进入拓扑排序
168     while (!IsEmpty())
169     {
170         int V = DeQueue();
171         TopOrder[cnt++] = V;
172         for (PtrToAdjVNode W = Graph->G[V].FirstEdge; W; W = W->Next)
173         {
174             if ((Earliest[V] + W->Weight) > Earliest[W->AdjV])
175                 Earliest[W->AdjV] = Earliest[V] + W->Weight;
176             if (--Indegree[W->AdjV] == 0)
177             {
178                 EnQueue(W->AdjV);
179             }
180         }
181     }
182     int Max = -1;  //计算最后一个元素的 Earliest
183     int V;            //记录最后一个任务
184     if (cnt != Graph->Nv)
185         return 0;
186     else
187     {
188         for (int i = 1; i <= Graph->Nv; i++)
189         {
190             if (Earliest[i] > Max)
191             {
192                 Max = Earliest[i];
193                 V = i;
194             }
195         }
196     }
197 
198     Clear();  //初始化队列
199     //从末尾开始计算Latest[];
200     int Outdegree[110];  //计算出度
201     for (int i = 1; i <= Graph->Nv; i++)    //最后一个元素的 Earliest与Latest 一样 为了保证任务肯定完成
202         Latest[i] = INFINITY;
203     Latest[V] = Max;
204     for (int i = 1; i <= Graph->Nv; i++)  //初始化出度
205         Outdegree[i] = 0; 
206     for (int i = 1; i <= Graph->Nv; i++)
207         for (PtrToAdjVNode W = Graph->G[i].FirstEdge; W; W = W->Next)
208             Outdegree[i]++;
209     for (int i = Graph->Nv; i > 0; i--)
210         if (Outdegree[i] == 0)  //首先将出度为0的元素 入队列
211             EnQueue(i);
212     //开始计算Latest[]
213     
214 
215     while (!IsEmpty())
216     {
217         int V = DeQueue();
218         for (PtrToAdjVNode W = Graph->G[V].LastEdge; W; W = W->Next)
219         {
220             if (Latest[V] - W->Weight < Latest[W->AdjV])
221                 Latest[W->AdjV] = Latest[V] - W->Weight;
222             if (--Outdegree[W->AdjV] == 0)
223                 EnQueue(W->AdjV);
224         }
225     }
226     //计算完Latest后 再来计算机动时间 并把机动时间为0的一对元素入队列
227     Clear();
228     for(int i=1;i<=Graph->Nv;i++)
229         for (PtrToAdjVNode W = Graph->G[i].FirstEdge; W; W = W->Next)
230         {
231             if (Latest[W->AdjV] - Earliest[i] - W->Weight == 0)
232             {
233                 EnQueue(i);
234                 EnQueue(W->AdjV);
235             }
236         }
237     return Max;
238 }
239 
240 int main()
241 {
242     LGraph Graph = BuildGraph();
243     int Sum;
244     if (!(Sum = TopSort(Graph)))
245         printf("0");
246     else   //找到最大的那个Earliest 并将已经处理好的 队列输出
247     {
248         printf("%d\n", Sum);
249         while (!IsEmpty())
250         {
251             printf("%d->", DeQueue());
252             printf("%d\n", DeQueue());
253         }
254             //printf("%d->%d\n", DeQueue(), DeQueue()); //注意函数读入顺序
255     }
256 }
View Code

相关文章:

  • 2021-11-27
  • 2022-12-23
  • 2022-12-23
  • 2021-12-16
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
  • 2022-12-23
猜你喜欢
  • 2022-12-23
  • 2022-12-23
  • 2021-04-08
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案