ALGO-5_蓝桥杯_最短路

时间:2020-12-09 00:00:57

记:

一开始没接触过关于最短距离的算法,便开始翻阅关于图的知识,

得知关于最短距离的算法有Dijkstra算法(堆优化暂未看懂),Bellman-Ford算法,Floyd算法,SPFA算法。

由于数据输入中存在负边,故可使用的有Dijkstra算法堆优化以及SPFA队列优化,

于是在网上找模版,却报出了运行错误。

也没看出问题,故翻阅他人笔记

其中一篇关于SPFA详解的blog:

http://blog.****.net/muxidreamtohit/article/details/7894298

让我恍然大悟,

然后就开始动笔...

第一次,10分  原因:没加结点的检查,造成死循环;

第二次,50分  原因:结点访问标记放在了判断最短距离的外面,造成了重复入队;

第三次,100分

 

源码如下:

  1 #include <stdio.h>
2 #include <stdlib.h>
3 #define MAX 99999999
4
5 typedef struct node node_t;
6 typedef struct node
7 {
8 int n ; /*指向的结点*/
9 int v ; /*边权值*/
10 node_t *next;
11 }node;
12 typedef node *node_p;
13 node_p *e = NULL;
14
15
16 int *d; /*到各点的距离*/
17 int *vis; /*用于纪录各结点的访问记录*/
18 int *line; /*队列*/
19 int rear = 0 , front = 0; /*队列的首尾标志*/
20 int n = 0 , m = 0 ; /*n个结点,m条边*/
21
22 void init() /*初始化,以及各结点间距离的登记*/
23 {
24 node *p;
25 int i = 0 , j = 0 ;
26 int x = 0 , y = 0 , v = 0 ;
27 scanf("%d %d",&n,&m);
28
29 d = (int *)malloc(sizeof(int)*(n+1));
30 vis = (int *)malloc(sizeof(int)*(n+1));
31 line = (int *)malloc(sizeof(int)*(n+1));
32 for (i = 1 ; i <= n ; i ++)
33 {
34 d[i] = MAX;
35 vis[i] = 0;
36 line[i] = 0;
37 }
38
39 e = (node_p *)malloc(sizeof(node_p)*(n+1));
40 for (i = 1 ; i <= n ; i ++)
41 {
42 e[i] = NULL;
43 }
44
45 /*处理成邻接表*/
46 for (i = 1 ; i <= m ; i ++)
47 {
48 scanf("%d %d %d",&x,&y,&v);
49 p = (node *)malloc(sizeof(node));
50 p->n = y ;
51 p->v = v ;
52 p->next = e[x];
53 e[x] = p;
54 }
55
56 return ;
57 }
58
59 void push(int x) /*进队列*/
60 {
61 front ++;
62 if (!line[front])
63 {
64 line[front] = x ;
65 }
66 if (front == n)
67 {
68 front = front%n;
69 }
70 return ;
71 }
72
73 int pop() /*出队列*/
74 {
75 int x = 0;
76 rear ++;
77 if (line[rear])
78 {
79 x = line[rear];
80 line[rear] = 0;
81 }
82 if (rear == n)
83 {
84 rear = rear%n;
85 }
86 return x;
87 }
88
89 void SPFA(int x)
90 {
91 node *p;
92 int i = 0 , k = 0;
93
94 d[x] = 0;
95 vis[x] = 1; /*访问x并标记*/
96 push(x); /*进队*/
97 i = n;
98 while (i)
99 {
100 k = pop(); /*出队*/
101 vis[k] = 0;
102 p = e[k];
103 i --;
104 while(p != NULL)
105 {
106 if (d[k]+p->v < d[p->n])
107 {
108 d[p->n] = d[k]+p->v;
109
110 if (!vis[p->n])/*未被标记的下一个结点将进队*/
111 {
112 vis[p->n] = 1;
113 push(p->n);
114 }
115 }
116 p = p->next;
117 }
118 }
119
120 /*打印到各点的距离*/
121 for (i = 2 ; i <= n ; i ++)
122 {
123 printf("%d\n",d[i]);
124 }
125
126 return ;
127 }
128
129 int main(void)
130 {
131 init();
132 SPFA(1);
133 return 0;
134 }