Dijkstra 算法

 Dijkstra(迪杰斯特拉)算法是典型的最短路径路由算法,用于计算一个节点到其他所有节点的最短路径。主要特点是以起始点为中心向外层层扩展,直到扩展到终点为止。Dijkstra算法能得出最短路径的最优解,但由于它遍历计算的节点很多,所以效率低。

其基本思想是,设置顶点集合S并不断地作贪心选择来扩充这个集合。一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。

初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的最短路径长度。

算法步骤:
1)  找到o到P中各点的最小值,经过查找o—x最小;
2)  找S中第一个点s0到集合P中所有点的最短距离,经过查找s0—px0最小,那么我们找S中第二个点s1集合P中所有点的最短距离,经过查找s1—px1最小,如此下去,直至我们找到了集合S中最后一个元素sn到P中所有点最短距离sn—pxm,这时我们需要找到o—s0—px0, o—s1—px1……o—sn—pxm中最短的一个o—si—pxj;
3)  比较o—x,o—si—pxj两条路径,如果前者更小则将x从P中剔除掉并纳入S中,如果后者更小则将pxj从P中剔除掉并纳入到S中,假设纳入到S中这个点位y,记录o—y的最小值,共以后计算使用;
4)  这一步我们要判断P是否为空集,如果P为空集算法结束,如果P中还有元素,重复上边三步。
#include<iostream>
#include<stdio.h>
#include<string.h>
#define N 100000000
using namespace std; 
int dist[205];            //记录源点到每个结点的最短路径 
int map[205][205];
bool visit[205];          //定义访问过的结点 
int n,m;
void init()               //init 通常做为 initialization 的缩写使用。即:设定初值,初始化的意思
{
     int i,j;
     for( i=0; i<n; i++){
          for( j=0; j<n; j++)
               map[i][j]=N;
          dist[i]=N;
          visit[i]=false;
     }
}

bool Dijkstra(int s,int t)   //s,t分别表示一个点到另一个点 
{
    int mim,k,i;
    dist[s]=0;               //该点到该点的最短路径为0 
    k=s;
    memset(visit,false,sizeof(visit));
    while( true){
           visit[k]=true;
           if( k==t)         //如果访问到所求点,跳出 
               break;
           for( i=0; i<n; i++)
                if( !visit[i]&&map[k][i]!=N) //如果该节点没有被访问过  并且  该节点和源点连通 
                    dist[i]=min(dist[i],dist[k]+map[k][i]);  // 求与源点连通的点中  与源点距离最短的点
           mim=N;
           k=-1;
           for( i=0; i<n; i++){
                if( !visit[i]&&mim>dist[i]){    //如果该点存在且最小 
                    mim=dist[i];
                    k=i;                         //变换下一个结点为k=i; 
                }
           }
           if( k==-1) break;              //如果不存在符合要求的与当前结点 相连的点  跳出  结束 
           
    }
    return k==t ? dist[t] :false;    //找到所求的点输出记录的最短距离 dist[t]    否则输出错误      
}
int main()
{
    int s,t,i,j,x;
    while( scanf("%d%d",&n,&m)!=EOF){
           init();//初始化 
           while( m--){
                  scanf("%d%d%d",&i,&j,&x);
                  if( x<map[i][j])              //相连通的点重新赋值 
                      map[i][j]=map[j][i]=x;
           }
           scanf("%d%d",&s,&t);
           printf("%d\n",Dijkstra(s,t));      
    }            
    return 0;
}


 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值