1. 程式人生 > >問題 F: 演算法7-15:迪傑斯特拉最短路徑演算法

問題 F: 演算法7-15:迪傑斯特拉最短路徑演算法

題目描述

在帶權有向圖G中,給定一個源點v,求從v到G中的其餘各頂點的最短路徑問題,叫做單源點的最短路徑問題。

在常用的單源點最短路徑演算法中,迪傑斯特拉演算法是最為常用的一種,是一種按照路徑長度遞增的次序產生最短路徑的演算法。

在本題中,讀入一個有向圖的帶權鄰接矩陣(即陣列表示),建立有向圖並按照以上描述中的演算法求出源點至每一個其它頂點的最短路徑長度。

輸入

輸入的第一行包含2個正整數n和s,表示圖中共有n個頂點,且源點為s。其中n不超過50,s小於n。

以後的n行中每行有n個用空格隔開的整數。對於第i行的第j個整數,如果大於0,則表示第i個頂點有指向第j個頂點的有向邊,且權值為對應的整數值;如果這個整數為0,則表示沒有i指向j的有向邊。當i和j相等的時候,保證對應的整數為0。

輸出

只有一行,共有n-1個整數,表示源點至其它每一個頂點的最短路徑長度。如果不存在從源點至相應頂點的路徑,輸出-1。

請注意行尾輸出換行。

樣例輸入

4 1
0 3 0 1
0 0 4 0
2 0 0 0
0 0 1 0

樣例輸出

6 4 7 

AC程式碼

#include<stdio.h> #include<string.h> #define N 9999999 int a[55][55],d[55],book[55]; int main() {     int n,s,i,j,u,l,min;     scanf("%d%d",&n,&s);     for(i=0;i<n;i++)     {         for(j=0;j<n;j++)         {             scanf("%d",&a[i][j]);             if(i!=j&&a[i][j]==0)             a[i][j]=N;         }     }          memset(d,0,sizeof(d));     memset(book,0,sizeof(book));          for(i=0;i<n;i++)     {         d[i]=a[s][i];     }          book[s]=1;          for(i=0;i<n;i++)     {         min=N;         for(j=0;j<n;j++)         {             if(min>d[j]&&book[j]==0)             {                 min=d[j];                 u=j;             }         }         book[u]=1;         for(l=0;l<n;l++)         {             if(a[u][l]<N)             {                 if(d[l]>d[u]+a[u][l])                 d[l]=d[u]+a[u][l];             }         }     }          for(i=0;i<n;i++)     {         if(i==s)         continue;         if(d[i]==N)         printf("-1 ");         else         printf("%d ",d[i]);     }     printf("\n");  }