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 }