-
-
- #include <iostream>
- #include <queue>
- using namespace std;
-
- #define MAXN 101
- #define INF 999999
-
- class Graph;
- class Vnode;
-
- class Arcnode
- {
- friend class Graph;
- friend class Vnode;
- private:
- int v;
- int weight;
- Arcnode *next;
- public:
- void Arcnode_Init(int e,int w)
- {
- v=e;
- weight=w;
- next=NULL;
- }
- };
-
- class Vnode
- {
- friend class Graph;
- private:
- int data;
- Arcnode *firstarc;
- public:
- void Vnode_init(int d)
- {
- data=d;
- firstarc=NULL;
- }
- };
-
- class DIj_Node
- {
- friend class Graph;
- public:
- int v;
- int dis;
- public:
- void Node_init(int dn,int dw)
- {
- v=dn;
- dis=dw;
- }
- friend bool operator < (const DIj_Node &a,const DIj_Node &b)
- {
- return (a.dis>b.dis);
- }
- };
-
- class Graph
- {
- private:
- Vnode head[MAXN];
- int vexsum;
- int arcsum;
- int dis[MAXN];
- int find[MAXN];
- public:
- void Graph_init(int n)
- {
- vexsum=n;
- for(int i=1;i<=n;i++)
- head[i].Vnode_init(i);
- }
-
- void Create_Graph(int m)
- {
- int i,s,e,w;
- Arcnode *temp_arc;
- for(i=1;i<=m;i++)
- {
- cout<<"输入第 "<<i<<" 条边的起点、终点和权值:";
- cin>>s>>e>>w;
- temp_arc = new Arcnode;
- temp_arc->Arcnode_Init(e,w);
- temp_arc->next=head[s].firstarc;
- head[s].firstarc=temp_arc;
- }
- arcsum=m;
- cout<<"建图完成"<<endl;
- }
-
- void Dijkstra(int src)
- {
- DIj_Node first,next,temp;
- priority_queue <DIj_Node> Q;
- Arcnode *arc;
- int i;
- for(i=1;i<=vexsum;i++)
- {
- dis[i]=INF;
- find[i]=false;
- }
- dis[src]=0;
- temp.Node_init(src,dis[src]);
- Q.push(temp);
-
- while(!Q.empty())
- {
- first=Q.top();
- Q.pop();
- find[first.v]=true;
-
- for(arc=head[first.v].firstarc;arc!=NULL;arc=arc->next)
- {
- if(find[arc->v])
- continue;
- next.Node_init(arc->v,first.dis+arc->weight);
- if(next.dis < dis[next.v])
- {
- dis[next.v]=next.dis;
- Q.push(next);
- }
- }
- }
- }
-
- void Print(int src)
- {
- for(int i=1;i<=vexsum;i++)
- {
- if(i == src)
- continue;
- if(dis[i] == INF)
- cout<<src<<" to "<<i<<"最短路径不存在"<<endl;
- else
- cout<<src<<" to "<<i<<" is: "<<dis[i]<<endl;
- }
- }
- };
-
- Graph G;
-
- int main()
- {
- int n,m,src,des;
- cout<<"输入顶点总数:";
- cin>>n;
- G.Graph_init(n);
- cout<<"输入边的总数:";
- cin>>m;
- G.Create_Graph(m);
-
-
-
- G.Dijkstra(1);
- G.Print(1);
- return 0;
- }
测试的数据和邻接矩阵+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的贪心是建立在边都是正边的基础上,这样,每次往前推进,路径长度都是变大的,如果出现负边,那么先前找到的最短路就不是真正的最短路,比如上边的例子,这个算法也就算废了。