输入:一个有向图,顶点个数 n ,然后是每条边的起点,终点,权值。顶点序号从0开始,-1 -1 -1表示结束。
输出:顶点0到其他各顶点的最短路径长度,并输出对应的最短路径。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cctype> 6 #include <stack> 7 #include <queue> 8 #include <map> 9 #include <set> 10 #include <vector> 11 #include <cmath> 12 #include <algorithm> 13 #define lson l, m, rt<<1 14 #define rson m+1, r, rt<<1|1 15 using namespace std; 16 typedef long long int LL; 17 const int MAXN = 0x3f3f3f3f; 18 const int MIN = -0x3f3f3f3f; 19 const double eps = 1e-9; 20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1}, 21 {1,1},{1,-1},{-1,-1}}; 22 const int MAX = 20; 23 int S[MAX], dist[MAX], path[MAX], edge[MAX][MAX]; 24 int n; 25 void Dijkstra(int v0) { 26 int i, j, k; 27 for (i = 0; i < n; ++i) { 28 dist[i] = edge[v0][i]; S[i] = 0; 29 if (i != v0 && edge[v0][i] != MAXN) path[i] = v0; 30 else path[i] = -1; 31 } 32 S[v0] = 1; dist[v0] = 0; 33 for (i = 0; i < n-1; ++i) { 34 int Min = MAXN, u = v0; 35 for (j = 0; j < n;++j) { 36 if (S[j] == 0 && dist[j] < Min) { 37 Min = dist[j]; u = j; 38 } 39 } 40 S[u] = 1; 41 for (j = 0; j < n; ++j) { 42 if (S[j] == 0 && edge[u][j] != MAXN) { 43 int tmp = edge[u][j] + dist[u]; 44 if (tmp < dist[j]) { 45 dist[j] = tmp; path[j] = u; 46 } 47 } 48 } 49 } 50 } 51 int main(void){ 52 #ifndef ONLINE_JUDGE 53 freopen("dijkstra.in", "r", stdin); 54 #endif 55 scanf("%d",&n); 56 int u, v, w, i, j, k; 57 while (1) { 58 scanf("%d%d%d", &u, &v, &w); 59 if (u == -1 && v == -1 && w == -1) break; 60 edge[u][v] = w; 61 } 62 for (i = 0; i < n;++i) { 63 for (j = 0; j < n; ++j) { 64 if (i == j) edge[i][j] = 0; 65 else if (edge[i][j] == 0) edge[i][j] = MAXN; 66 } 67 } 68 Dijkstra(0); 69 for (i = 1; i < n;++i) { 70 printf("%d\t", dist[i]); 71 int Shortest[MAX]; k = 0; 72 Shortest[k] = i; 73 while (path[Shortest[k]] != 0) { 74 ++k; Shortest[k] = path[Shortest[k-1]]; 75 } 76 ++k; Shortest[k] =0; 77 for (j = k; j > 0; --j) { 78 printf("%d->", Shortest[j]); 79 } 80 printf("%d\n", Shortest[0]); 81 } 82 83 return 0; 84 }
采用所谓的“倒向追踪”的方法记录最短路径的时候,要注意怎么存储路径。写的时候,这里出现了一个bug。
输出路径的时候,赶脚书上的写法有点儿挫……所以自己又写了一遍。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cstring> 5 #include <cctype> 6 #include <stack> 7 #include <queue> 8 #include <map> 9 #include <set> 10 #include <vector> 11 #include <cmath> 12 #include <algorithm> 13 #define lson l, m, rt<<1 14 #define rson m+1, r, rt<<1|1 15 using namespace std; 16 typedef long long int LL; 17 const int MAXN = 0x7fffffff; 18 const int MINN = -0x7fffffff; 19 const double eps = 1e-9; 20 const int dir[8][2] = {{0,1},{1,0},{0,-1},{-1,0},{-1,1}, 21 {1,1},{1,-1},{-1,-1}}; 22 const int MAX = 200; 23 int edge[MAX][MAX], dist[MAX], path[MAX]; bool S[MAX]; 24 int n, m; 25 void Dijkstra(int u0) { 26 int i, j, k, u, Min; 27 for (i = 0; i < n; ++i) { 28 dist[i] = edge[u0][i]; S[i] = false; 29 if (u0!=i && edge[u0][i] != MAXN) path[i] = u0; 30 else path[i]= -1; 31 } 32 S[i] = true; dist[u0] = 0; path[u0] = -1; 33 for (i = 1; i < n; ++i) { 34 u = u0; Min = MAXN; 35 for (j = 0; j < n; ++j) { 36 if (S[j] == false && dist[j] < Min) { 37 Min = dist[j]; u = j; 38 } 39 } 40 S[u] = true; 41 for (j = 0; j < n; ++j) { 42 if (S[j] == false && edge[u][j] != MAXN) { 43 int tmp= edge[u][j] + dist[u]; 44 if (tmp < dist[j]) { 45 dist[j] = tmp; 46 path[j] = u; 47 } 48 } 49 } 50 } 51 } 52 53 int main(void){ 54 #ifndef ONLINE_JUDGE 55 freopen("dijkstra.in", "r", stdin); 56 #endif 57 int u, v, w; 58 memset(edge, 0, sizeof(edge)); 59 scanf("%d", &n); 60 while (1) { 61 scanf("%d%d%d", &u, &v, &w); 62 if (u == -1 && v == -1 && w == -1) break; 63 edge[u][v] = w; 64 } 65 int i, j, k; 66 for (i = 0; i < n; ++i) { 67 for (j = 0; j < n; ++j) { 68 if (i == j) edge[i][j] = 0; 69 else if(edge[i][j] == 0) edge[i][j] = MAXN; 70 } 71 } 72 int Path[MAX]; Dijkstra(0); 73 for (i = 1; i < n; ++i) { 74 printf("%d\t",dist[i]); 75 k= 0; Path[0] = i; int ho = path[i]; 76 while (ho != -1) { 77 Path[++k] = ho; ho = path[ho]; 78 } 79 for (j = k; j > 0; --j) printf("%d->", Path[j]); 80 printf("%d\n", Path[0]); 81 } 82 83 return 0; 84 }
因为做了两道题目,都没有要求输出路径的,所以自己还是写一下输出路径的吧。注意一下,开始标记路径的时候,把和u0相连的标记为u0,其它的不相连的标记为-1.循环结束后,把path[u0]标记为-1,表示起点。Dijkstra算法最后求得的dist[]是u0到每个点的最短距离。
现在感觉,平时就要有意识地训练一下自己的查错能力,这样,真正比赛的时候,就不会因为找不出来错而着急了。