ALGO-5_蓝桥杯_算法训练_最短路

记:

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

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

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

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

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

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

http://blog.csdn.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 }

 

转载于:https://www.cnblogs.com/mind000761/p/8508981.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值