【作业存档】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 }

 

 

 

posted @ 2016-12-03 20:30  kenkuuuun  阅读(369)  评论(0)    收藏  举报