圖結構練習——最短路徑(Dijkstra)
阿新 • • 發佈:2019-02-09
圖結構練習——最短路徑
Time Limit: 1000 ms Memory Limit: 65536 KiB
Problem Description
給定一個帶權無向圖,求節點1到節點n的最短路徑。
Input
輸入包含多組資料,格式如下。
第一行包括兩個整數n m,代表節點個數和邊的個數。(n<=100)
剩下m行每行3個正整數a b c,代表節點a和節點b之間有一條邊,權值為c。
Output
每組輸出佔一行,僅輸出從1到n的最短路徑權值。(保證最短路徑存在)
Sample Input
3 2
1 2 1
1 3 1
1 0
Sample Output
1
0
#include <stdio.h> #include <string.h> #define INF 0x3f3f3f3f int map[105][105];//標示圖的座標 int vis[105]; //表示是否參觀過 int dist[105]; //權值和 void Dijkstra(int n) //n為終點 { int i, j, k, min, u; for(i = 1;i <= n;i++) { dist[i] = map[1][i];//1為起點,將1到的i點得距離存進去 } vis[1] = 1; //走過的標記 for(i = 1;i < n;i++) //進行n-1次查詢,對每個節點都找一次,看有沒有更小的路徑 { min = INF; for(j = 1;j <= n;j++) { if(min > dist[j] && !vis[j])//找出沒有被標記,並且距離起始點最近的點 { min = dist[j]; //記錄大小 u = j; //記錄第幾個點 } } vis[u] = 1; //標記一下 for(k = 1;k <= n;k++) { //更新dist的值 if(!vis[k] && map[u][k] < INF && dist[k] > map[u][k] + dist[u]) { dist[k] = map[u][k] + dist[u]; } } } printf("%d\n",dist[n]); } int main() { int n, m, u, v, c, i; while(~scanf("%d %d",&n, &m)) { memset(vis,0,sizeof(vis)); memset(map,INF,sizeof(map));//先全為無窮大 for(i = 1;i <= n;i++) { map[i][i] = 0; //初始化map[][]陣列,除去自己本身,距離為0,其他全設為無窮大 } while(m--) { scanf("%d %d %d",&u,&v,&c);//輸入 if(map[u][v] > c) { map[u][v] = map[v][u] = c; } } Dijkstra(n);//呼叫函式 } return 0; }
模板程式碼
#include<stdio.h> #include<string.h> #define INF 0x3f3f3f3f int map[550][550]; int vis[550]; int dist[550]; void Dijkstra(int n, int s, int d) { int i, j, k, min, u; for(i = 0;i< n;i++) { dist[i] = map[s][i]; } dist[s] = 0; vis[s] = 1; for(i =1 ;i < n;i++) { min = INF; for(j = 0;j < n;j++) { if(min > dist[j] && !vis[j]) { min = dist[j]; u = j; } } vis[u] = 1; for(k = 0;k < n;k++) { if(!vis[k] && map[u][k] < INF && dist[u] + map[u][k] < dist[k]) { dist[k] = dist[u] + map[u][k]; } } } printf("%d\n",dist[d]); }