最短路径:Dijkstra——初探

//算法:Dijkstra
//主要思想(贪心):将图分为两部分:已确定离源点s最短距离的节点集合Q与未确定的集合P;
// 

         初始化:将dist[s]=0;visted[s]=1;
//          循环:在未确定集合P中寻找离源点最短距离的节点,并且然后对于其余未确定的节点进行松弛;
//          终止:visted中的所有元素均为1
//算法正确性的简单证明(数学归纳):
//1,当n=1时,即确定的集合中元素只有源点s时,显然是集合中的元素离源点都是最短的;
//2,假设当n=k时即确定最短路径的集合中元素个数为k,结论正确;
//   那么n=k+1时即加入的第k+1个元素g是未确定最短路径的集合P中离源点最近的;
//              若此时dist[g]不是最终离源点最近的路径l',则在路径l'上必存在一点集合P中的元素h,使得g的路径松弛以得到更短路径.
//              那么dist[h]肯定小于dist[g],与假设不符{在集合P中,元素g的dist[g]最小}
//              所以此时加入的是即将确定的最短路径。
//    由1>,2>证得最终得到的集合Q即为最短路径集合。
//      
//    另外此代码实现的过程中,有一点要注意,dist[i]一旦确定,其值则不会改变!【同样用反证法可以证明】
#include <stdio.h>
#include <memory.h>
#define MAXN 10000
#define INF (1<<30)
int V[MAXN][MAXN],visted[MAXN],dist[MAXN],num;//V:邻接阵表示图;visted:是否访问过 dist:表示源点到该节点的最短距离
void relax(int a,int b){if(dist[a]+V[a][b]<dist[b]) dist[b]=dist[a]+V[a][b];}//松弛
void Dijkstra(int n);
int main()
{
    int i,n,temp_1,temp_2,temp_3,sum,j;

    scanf("%d%d",&num,&sum);

    memset(visted,0,sizeof(visted));//初始化visted数组
    
    for(i=0;i<num;i++)dist[i]=INF;//初始化dist数组
    for(i=0;i<num;i++)
    for(j=0;j<num;j++)
    V[i][j]=INF;

    for(i=0;i<sum;i++)
    {
        scanf("%d%d%d",&temp_1,&temp_2,&temp_3);
        V[temp_1][temp_2]=temp_3;
    }
    scanf("%d",&n);
    for(i=0;i<num;i++)
    if(V[n][i]!=INF)dist[i]=V[n][i];

    Dijkstra(n);

    for(i=0;i<num;i++)
    printf("%d-%dmin:%d\t",n,i,i==n?0:dist[i]);

    return 0;
}


void Dijkstra(int n)
{
    int i,min,min_i;
    visted[n]=1;
    do{
      min_i=-1;
      for(i=0;i<num;i++)  //找出在未确定最短路径的集合中寻找离源点最近的节点
      {
          if(!visted[i])
          {
              if(min_i==-1||dist[i]<min)
              min_i=i,min=dist[i];
          }
      }
      if(min_i==-1)break;

      visted[min_i]=1;

    for(i=0;i<num;i++)   //松弛
    if(V[min_i][i]&&V[min_i][i]+dist[min_i]<dist[i])
    dist[i]=V[min_i][i]+dist[min_i];
    }while(1);
}

posted on 2011-07-21 12:11  sleeper_qp  阅读(219)  评论(0编辑  收藏  举报

导航