对Dijkstra算法不是很熟悉,写一下思路,希望通过写博客加深理解
Description
现在,已知起点和终点,请你计算出要从起点到终点,最短需要行走多少距离。
Input
每组数据第一行包含两个正整数N和M(0<N<200,0<M<1000),分别代表现有城镇的数目和已修建的道路的数目。城镇分别以0~N-1编号。
接下来是M行道路信息。每一行有三个整数A,B,X(0<=A,B<N,A!=B,0<X<10000),表示城镇A和城镇B之间有一条长度为X的双向道路。
再接下一行有两个整数S,T(0<=S,T<N),分别代表起点和终点。
Output
Sample Input
#include <stdio.h> #define M 210 #define INF 0x3f3f3f int arr[M][M], vis[M], dis[1010]; int n, m; void Dijkstra(int src) { for(int i = 0; i < n; i++) { vis[i] = 0; dis[i] = arr[src][i]; } int tmp, k; vis[src] = 1; dis[src] = 0; for(int i = 0; i < n; i++) { tmp = INF; for(int j = 0; j < n; j++) { if(!vis[j] && tmp > dis[j]) { tmp = dis[j]; k = j; } } vis[k] = 1; for(int j = 0; j < n; j++) { if(!vis[j] && dis[j] > arr[k][j] + dis[k]) dis[j] = arr[k][j] + dis[k]; } } } int main() { int s, t, u, v, w; while(~scanf("%d%d", &n, &m)) { for(int i = 0; i < n; i++) { for(int j = 0; j < n; j++) arr[i][j] = INF; } for(int i = 0; i < m; i++) { scanf("%d%d%d", &u, &v, &w); if(arr[u][v] > w) arr[u][v] = arr[v][u] = w; } scanf("%d%d", &s, &t); Dijkstra(s); if(dis[t] == INF) printf("-1 "); else printf("%d ", dis[t]); } return 0; }
上一个代码是我以前参考别人的代码写的,今天又看了这道题,自己写了代码
刚开始一直wrong answer ,竟然一直找不到原因,后来发现我没有考虑从本城市到本城市的情况,初始化的时候arr[i][i] = 0
因为这个,wrong answer 10发,真是醉了
/*
问题:假设所有城市编号0到n-1,给出城市的数目n,已经修的路的数目m,m行给出m条路中a城和b成的距离x
输入出发城市s和目标城市t,问从出发城市到目标城市的最短路线
如果没有路,输出-1
分析:把出发的点s带入Dijkstra算法进行计算,算出所有点到src的最短距离,输出arr[src][t]即可
代码块1:初始化
1:把所有点之间的距离初始化为无穷,
2:别忘了把自己到自己的距离初始化为0(因为这个原因wrong answer 10 发,真的够了)
3:录入输入的城市a到城市b的距离x,如果x小于原本存储的arr[a][b](也就是a城市到b城市的距离)那么就更新a城市到b城市的距离
代码块2:Dijkstra算法:
1:把所有的城市标记为临时的
2:共有n个城市,先把出发的城市标记为永久的,因为每次把一个城市标记为临时的所以还要循环n-1次来标记其他的城市,直到所有城市都为永久
3:每次的循环中找到所有城市中距离起点最近的城市k,并把这个城市标记为永久,更新其他所有城市,假设为"i"到到起点的距离为min(arr[s][k]+arr[k][i], arr[s][i]);
这样就找到了所有城市距离起点s的最短距离,输出arr[s][t]即可
*/
代码2:
#include <stdio.h> #include <string.h> #include <algorithm> #define M 1000+10 #define INF 0x3f3f3f using namespace std; int arr[M][M]; bool vis[M]; int n, m; void Init() { int a, b, x; for(int i = 0; i < n; i++) for(int j = 0; j < n; j++) arr[i][j] = INF; for(int i = 0; i < n; i++) arr[i][i] = 0; for(int i = 0; i < m; i++) { scanf("%d%d%d", &a, &b, &x); if(x < arr[a][b]) arr[a][b] = arr[b][a] = x; } } void Dijkstra(int src) { int tmp, k; memset(vis, 0, sizeof(vis)); vis[src] = 1; arr[0][0] = 0; for(int i = 1; i < n; i++) { tmp = INF; for(int j = 0; j < n; j++) { if(arr[src][j] < tmp && !vis[j]) { tmp = arr[src][j]; k = j; } } vis[k] = 1; //把找到的那个点标记为永久 for(int j = 0; j < n; j++) { if(arr[src][k]+arr[k][j] < arr[src][j]) arr[src][j] = arr[src][k] + arr[k][j]; } } } int main() { int s, t; //freopen("input.txt", "r", stdin); while(~scanf("%d%d", &n, &m)) { Init(); scanf("%d%d", &s, &t); Dijkstra(s); if(arr[s][t] != INF) printf("%d ", arr[s][t]); else printf("-1 "); } return 0; }