題目描述
在帶權有向圖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
提示
在本題中,需要按照題目描述中的算法完成迪傑斯特拉算法,並在計算最短路徑的過程中將每個頂點是否可達記錄下來,直到求出每個可達頂點的最短路徑之後,算法才能夠結束。
迪傑斯特拉算法的特點是按照路徑長度遞增的順序,依次添加下一條長度最短的邊,從而不斷構造出相應頂點的最短路徑。
另外需要注意的是,在本題中爲了更方便的表示頂點間的不可達狀態,可以使用一個十分大的值作爲標記。
#include<stdio.h>
#define inf 0x3fffffff
int a[60][60];
int n, s;
int max(int x, int y)
{
if(x > y) return x;
return y;
}
void dijstra(int s)
{
int dis[100];
int vis[100];
for(int i=0; i<n; i++)
{
dis[i] = inf;//距離爲最大
vis[i] = 0; //未訪問過
}
dis[s] = 0;
int min, k;
for(int i=0; i<n; i++)
{
min = inf;
for(int j=0; j<n; j++)
{
if(vis[j]==0 && dis[j] < min)//找到未訪問中最小的點
{
k = j;
min = dis[j];
}
}
vis[k] = 1;//加入訪問後的集合
for(int j=0; j<n; j++)
{
if(vis[j]==0&&dis[k]+a[k][j] < dis[j])//沒訪問過
dis[j] = dis[k] + a[k][j];
}
}
for(int i=0; i<n; i++)
{
if(i!=s && dis[i]!=inf)
{
printf("%d ", dis[i]);
}
if(i!=s && dis[i] == inf)
printf("-1 ");
}
printf("\n");
}
int main()
{
while(scanf("%d%d",&n,&s)!=EOF)
{
for(int i=0; i<n; i++)
for(int j=0; j<n; j++)
{
scanf("%d",&a[i][j]);
if(a[i][j]==0)
a[i][j] = inf;
}
dijstra(s);
}
}