【作业存档】Dijkstra算法的练习
1 #include <stdio.h> 2 #include <stdlib.h> 3 4 typedef enum { false, true } bool; 5 #define INFINITY 1000000 6 #define MaxVertexNum 10 /* maximum number of vertices */ 7 typedef int Vertex; /* vertices are numbered from 0 to MaxVertexNum-1 */ 8 typedef int WeightType; 9 10 typedef struct GNode *PtrToGNode; 11 struct GNode{ 12 int Nv; 13 int Ne; 14 WeightType G[MaxVertexNum][MaxVertexNum]; 15 }; 16 typedef PtrToGNode MGraph; 17 18 MGraph ReadG(); /* details omitted */ 19 20 void ShortestDist(MGraph Graph, int dist[], int count[], Vertex S); 21 22 int main() 23 { 24 int dist[MaxVertexNum], count[MaxVertexNum]; 25 Vertex S, V; 26 MGraph G = ReadG(); 27 28 scanf("%d", &S); 29 ShortestDist(G, dist, count, S); 30 31 for (V = 0; V<G->Nv; V++) 32 printf("%d ", dist[V]); 33 printf("\n"); 34 for (V = 0; V<G->Nv; V++) 35 printf("%d ", count[V]); 36 printf("\n"); 37 38 return 0; 39 } 40 41 42 typedef struct Queue * queue; 43 struct Queue{ 44 int VNode; 45 queue next; 46 }; 47 48 typedef struct Q *q; 49 struct Q{ 50 queue header; 51 queue tail; 52 }; 53 54 void Push(int V, q Q){ 55 queue tmp; 56 tmp = (queue)malloc(sizeof(struct Queue)); 57 tmp->VNode = V; 58 tmp->next = NULL; 59 Q->tail->next = tmp; 60 Q->tail = tmp; 61 } 62 63 int Pop(q Q){ 64 int V; 65 queue tmp; 66 tmp = Q->header->next; 67 if (!tmp) 68 return -1; 69 if (tmp == Q->tail) 70 Q->tail = Q->header; 71 72 V = tmp->VNode; 73 Q->header->next = tmp->next; 74 75 free(tmp); 76 return V; 77 } 78 79 80 void ShortestDist(MGraph Graph, int dist[], int count[], Vertex S){ 81 q Q = (q)malloc(sizeof(struct Q)); 82 bool visit[MaxVertexNum][MaxVertexNum]; 83 int count2[MaxVertexNum]; 84 Vertex V, W; 85 int i,j,tmpDis = 0,tmpC = 0; 86 87 for (i = 0; i < Graph->Nv; i++) { 88 dist[i] = -1; 89 count[i] = 0; 90 for (j = 0; j < Graph->Nv; j++) 91 visit[i][j] = 0; 92 count2[i] = 0; 93 } 94 dist[S] = 0; 95 count[S] = 1; 96 count2[S] = 0; 97 Q->header = (queue)malloc(sizeof(struct Queue)); 98 Q->header->next = NULL; 99 Q->header->VNode = -1; 100 Q->tail = Q->header; 101 102 Push( S,Q); 103 while ((V = Pop(Q)) >= 0){ 104 for (W = 0; W < Graph->Nv; W++){ 105 if (Graph->G[V][W] > 0){ 106 tmpDis = dist[V] + Graph->G[V][W]; 107 if (dist[W] == -1 || tmpDis < dist[W]){ 108 dist[W] = tmpDis; 109 count2[W] = count[W]; 110 count[W] = count[V]; 111 Push(W, Q); 112 for (j = 0; j < Graph->Nv; j++) 113 visit[W][j] = 0; 114 visit[W][V] = count[V]; 115 } 116 else if (tmpDis == dist[W]){ 117 count2[W] = count[W]; 118 if (visit[W][V]){ 119 count[W] = count[W] + count[V] - visit[W][V]; 120 } 121 else 122 count[W] += count[V]; 123 124 visit[W][V] = count[V]; 125 Push(W, Q); 126 } 127 128 } 129 } 130 } 131 } 132 133 134 MGraph ReadG() 135 { 136 int i, j; 137 int w, v, x; 138 MGraph p; 139 p = (PtrToGNode)malloc(sizeof(struct GNode)); 140 scanf("%d%d", &w, &v); 141 p->Nv = w, p->Ne = v; 142 for (i = 0; i<p->Nv; i++){ 143 for (j = 0; j<p->Nv; j++){ 144 p->G[i][j] = -1; 145 } 146 } 147 for (i = 0; i<p->Ne; i++){ 148 scanf("%d%d%d", &w, &v, &x); 149 p->G[w][v] = x; 150 } 151 return p; 152 }
void ShortestDist( MGraph Graph, int dist[], int count[], Vertex S );
用这个函数实现,找到图中每个点到源所有的加权最短路径,记录下总长度(边的权值和)和条数。如果不相连,总长度为-1和条数0
dist记录总长度,count记录找到了几条这样的路径。
注:这里使用矩阵来表示图的
【知识点复习】:行代表出发的结点,列代表进入的节点
【算法实现】:Dijkstra算法的变形。从源出发,遍历其所有临近的结点,如果现在的dist比记录中的短(或为-1),count数归零后继承前一个结点的count数,改变dist值;如果相等,count += 前一个结点的count数,每改变某一个结点的,就将该结点放到队列中。
V1:答案错误,检查了一下有三个错误
Push写的位置不对
for循环中因为之前把i改成了W没改全(……)
一开始忘了吧源的count初始化为1了
V2:只有第三个测试点对了,似乎是count出了问题,如果曾经count过的点改变后会重复count
V3:改正了count的问题,能够正确输出例子,但是就是不能通过pta(QAQ)而且还用到了很多空间,决定按常规算法orz
两次Dijkstra算法的版本
1 void ShortestDist(MGraph Graph, int dist[], int count[], Vertex S){ 2 int dist2[MaxVertexNum]; 3 bool isVisit[MaxVertexNum]; 4 int i, minDis,V, W, tmpDis; 5 6 for (i = 0; i < Graph->Nv; i++){ 7 dist[i] = INFINITY; 8 dist2[i] = INFINITY; 9 count[i] = 0; 10 isVisit[i] = false; 11 } 12 dist[S] = 0; 13 dist2[S] = 0; 14 count[S] = 1; 15 16 for (i = 0; i<Graph->Nv; i++){ 17 if (Graph->G[S][i]>0){ 18 dist[i] = Graph->G[S][i]; 19 } 20 } 21 22 isVisit[S] = true; 23 dist[S] = 0; 24 25 while (1){ 26 V = -1; 27 minDis = INFINITY; 28 29 for (i = 0; i < Graph->Nv; i++){ 30 if (!isVisit[i] && dist[i] < minDis){ 31 V = i; 32 minDis = dist[V]; 33 } 34 } 35 if (V == -1) break; 36 isVisit[V] = true; 37 38 for (W = 0; W < Graph->Nv; W++){ 39 tmpDis = dist[V] + Graph->G[V][W]; 40 if (!isVisit[W]&&Graph->G[V][W] > 0 && tmpDis < dist[W]){ 41 dist[W] = tmpDis; 42 } 43 } 44 } 45 46 for (i = 0; i < Graph->Nv; i++){ 47 if (dist[i] == INFINITY) 48 dist[i] = -1; 49 isVisit[i] = false; 50 } 51 52 53 isVisit[S] = true; 54 count[S] = 1; 55 dist2[S] = 0; 56 57 for (i = 0; i<Graph->Nv; i++){ 58 if (Graph->G[S][i]>0){ 59 dist2[i] = Graph->G[S][i]; 60 if (dist2[i] == dist[i]){ 61 count[i] = 1; 62 } 63 } 64 } 65 66 67 while (1){ 68 V = -1; 69 minDis = INFINITY; 70 71 for (i = 0; i < Graph->Nv; i++){ 72 if (!isVisit[i] && dist2[i] < minDis){ 73 V = i; 74 minDis = dist2[V]; 75 } 76 } 77 if (V == -1) break; 78 isVisit[V] = true; 79 80 for (W = 0; W < Graph->Nv; W++){ 81 tmpDis = dist2[V] + Graph->G[V][W]; 82 if (Graph->G[V][W] > 0 && tmpDis < dist2[W]){ 83 dist2[W] = tmpDis; 84 count[W] = count[V]; 85 } 86 else if (Graph->G[V][W] > 0 && tmpDis == dist2[W]){ 87 count[W] += count[V]; 88 } 89 } 90 } 91 92 }

浙公网安备 33010602011771号