优化dijkstra算法

[cpp]  view plain  copy
 print ?
  1. //邻接表+优先队列+Dijkstra模版  
  2.   
  3. #include <iostream>  
  4. #include <queue>  
  5. using namespace std;  
  6.   
  7. #define MAXN 101  
  8. #define INF 999999  
  9.   
  10. class Graph;  //有向图  
  11. class Vnode;  //头结点  
  12.   
  13. class Arcnode  //表结点  
  14. {  
  15.     friend class Graph;  
  16.     friend class Vnode;  
  17. private:  
  18.     int v;  
  19.     int weight;  
  20.     Arcnode *next;  
  21. public:  
  22.     void Arcnode_Init(int e,int w)  
  23.     {  
  24.         v=e;  
  25.         weight=w;  
  26.         next=NULL;  
  27.     }  
  28. };  
  29.   
  30. class Vnode   //头结点  
  31. {  
  32.     friend class Graph;  
  33. private:  
  34.     int data;  
  35.     Arcnode *firstarc;  
  36. public:  
  37.     void Vnode_init(int d)  
  38.     {  
  39.         data=d;  
  40.         firstarc=NULL;  
  41.     }  
  42. };  
  43.   
  44. class DIj_Node  //用于求最短路时候的顶点  
  45. {  
  46.     friend class Graph;  
  47. public:  
  48.     int v;  
  49.     int dis;  
  50. public:  
  51.     void Node_init(int dn,int dw)  
  52.     {  
  53.         v=dn;  
  54.         dis=dw;  
  55.     }  
  56.     friend bool operator < (const DIj_Node &a,const DIj_Node &b)  //是优先队列的队头是最小值  
  57.     {  
  58.         return (a.dis>b.dis);  
  59.     }  
  60. };  
  61.   
  62. class Graph  
  63. {  
  64. private:  
  65.     Vnode head[MAXN];  //头结点数组  
  66.     int vexsum;  //顶点总数  
  67.     int arcsum;  //边总数  
  68.     int dis[MAXN];  //存源点到该顶点的最短路径长度  
  69.     int find[MAXN];  //是否已找到最短路径的标志  
  70. public:  
  71.     void Graph_init(int n)  
  72.     {  
  73.         vexsum=n;  
  74.         for(int i=1;i<=n;i++)  
  75.             head[i].Vnode_init(i);  
  76.     }  
  77.   
  78.     void Create_Graph(int m)  
  79.     {  
  80.         int i,s,e,w;  
  81.         Arcnode *temp_arc;  
  82.         for(i=1;i<=m;i++)  
  83.         {  
  84.             cout<<"输入第 "<<i<<" 条边的起点、终点和权值:";  
  85.             cin>>s>>e>>w;  
  86.             temp_arc = new Arcnode;  
  87.             temp_arc->Arcnode_Init(e,w);  
  88.             temp_arc->next=head[s].firstarc;  
  89.             head[s].firstarc=temp_arc;  
  90.         }  
  91.         arcsum=m;  
  92.         cout<<"建图完成"<<endl;  
  93.     }  
  94.   
  95.     void Dijkstra(int src)  
  96.     {  
  97.         DIj_Node first,next,temp;  
  98.         priority_queue <DIj_Node> Q;  
  99.         Arcnode *arc;  
  100.         int i;  
  101.         for(i=1;i<=vexsum;i++)  
  102.         {  
  103.             dis[i]=INF;  
  104.             find[i]=false;  
  105.         }  
  106.         dis[src]=0;  
  107.         temp.Node_init(src,dis[src]);  
  108.         Q.push(temp);  
  109.   
  110.         while(!Q.empty())  
  111.         {  
  112.             first=Q.top();  
  113.             Q.pop();  
  114.             find[first.v]=true;  
  115.   
  116.             for(arc=head[first.v].firstarc;arc!=NULL;arc=arc->next)  
  117.             {  
  118.                 if(find[arc->v])  
  119.                     continue;  
  120.                 next.Node_init(arc->v,first.dis+arc->weight);  
  121.                 if(next.dis < dis[next.v])  
  122.                 {  
  123.                     dis[next.v]=next.dis;  
  124.                     Q.push(next);  
  125.                 }  
  126.             }  
  127.         }  
  128.     }  
  129.   
  130.     void Print(int src)  
  131.     {  
  132.         for(int i=1;i<=vexsum;i++)  
  133.         {  
  134.             if(i == src)  
  135.                 continue;  
  136.             if(dis[i] == INF)  
  137.                 cout<<src<<" to "<<i<<"最短路径不存在"<<endl;  
  138.             else  
  139.                 cout<<src<<" to "<<i<<" is: "<<dis[i]<<endl;  
  140.         }  
  141.     }  
  142. };  
  143.   
  144. Graph G;  
  145.   
  146. int main()  
  147. {  
  148.     int n,m,src,des;  
  149.     cout<<"输入顶点总数:";  
  150.     cin>>n;  
  151.     G.Graph_init(n);  
  152.     cout<<"输入边的总数:";  
  153.     cin>>m;  
  154.     G.Create_Graph(m);  
  155.     //cout<<"输入源点和终点:";  
  156.     //cin>>src>>des;  
  157.     //cout<<G.Dijkstra(src,des)<<endl;  
  158.     G.Dijkstra(1);  
  159.     G.Print(1);  
  160.     return 0;  
  161. }  

测试的数据和邻接矩阵+Dijkstra实现是一样的,这个是以前写的,效率较低,最容易理解的Dijkstra算法。上面的是用优先队列进行优化,以及用邻接表进行存储的实现。

Dijkstra由于是贪心的,每次都找一个距源点最近的点(dmin),然后将该距离定为这个点到源点的最短路径(d[i] ← dmin);但如果存在负权边,那就有可能先通过并不是距源点最近的一个次优点(dmin’),再通过这个负权边 L (L < 0),使得路径之和更小(dmin’ + L < dmin),则 dmin’ + L 成为最短路径,并不是dmin,这样Dijkstra就被囧掉了。比如n = 3,邻接矩阵:

0, 3, 4

3, 0,-2

4,-2, 0

     用Dijkstra求得 d[1,2] = 3,事实上 d[1,2] = 2,就是通过了 1-3-2 使得路径减小。Dijkstra的贪心是建立在边都是正边的基础上,这样,每次往前推进,路径长度都是变大的,如果出现负边,那么先前找到的最短路就不是真正的最短路,比如上边的例子,这个算法也就算废了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值