最短路问题,只是牵扯到了字符串的操作。题目是中文描述就不多说了。因为这道题不像普通的最短路问题以数字来给地点编号,而是以地点的名称来确定,所以更加结合实际问题,但是又不方便解题。那么应该把地点的名称用数字来编号,把名称转换成编号来解题,这才是关键。
注意:此题中的路为无向的;如果无法从起点到达终点,输出为-1,这是题目没有说明的;如果起点就是终点,输出为0。此题用C或C++编译器的运行时间比GCC和G++短。
下面是解题代码:Dijkstra解法
1 #include <stdio.h> 2 #include <string.h> 3 #define N 151 4 #define NAME 31 5 #define INF 99999999 6 7 int map[N][N]; 8 int dis[N]; //从起点到编号为下标的地点的距离 9 int flag[N]; 10 char name[N][NAME]; 11 int na; //站点的个数 12 int n; //道路的个数 13 14 void Init(); //初始化 15 16 void Read(); //输入 17 18 int Count(char s[]); //计算字符串对应的编号 19 20 void Dijkstra(); 21 22 int main() 23 { 24 while (~scanf("%d", &n)) 25 { 26 if (n == -1) break; 27 Init(); 28 Read(); 29 Dijkstra(); 30 if (strcmp(name[1], name[0]) == 0) 31 { 32 printf("0 "); 33 continue; 34 } 35 printf("%d ", dis[1] == INF ? -1 : dis[1]); 36 } 37 return 0; 38 } 39 40 void Init() //初始化 41 { 42 int i, j; 43 for (i=0; i<N; ++i) 44 { 45 for (j=0; j<N; ++j) 46 { 47 map[i][j] = INF; 48 } 49 dis[i] = INF; 50 flag[i] = 0; 51 } 52 scanf("%s %s", name[0], name[1]); 53 na = 2; 54 return; 55 } 56 57 void Read() //输入 58 { 59 int i; 60 char sa[NAME], sb[NAME]; 61 int a, b, c; 62 for (i=0; i<n; ++i) 63 { 64 scanf("%s %s %d", sa, sb, &c); 65 a = Count(sa); 66 b = Count(sb); 67 map[a][b] = map[b][a] = c; 68 } 69 return; 70 } 71 72 int Count(char s[]) //计算字符串对应的编号 73 { 74 int i; 75 for (i=0; i<na; ++i) 76 { 77 if (strcmp(name[i], s) == 0) 78 { 79 return i; 80 } 81 } 82 strcpy(name[na++], s); 83 return (na - 1); 84 } 85 86 void Dijkstra() 87 { 88 int i, j, k; 89 int min; 90 dis[0] = 0; 91 for (j=0; j<na; ++j) 92 { 93 min = INF; 94 for (i=0; i<na; ++i) 95 { 96 if (flag[i] == 0 && min > dis[i]) 97 { 98 min = dis[k = i]; 99 } 100 } 101 flag[k] = 1; 102 for (i=0; i<na; ++i) 103 { 104 if (flag[i] == 0 && dis[i] > dis[k] + map[k][i]) 105 { 106 dis[i] = dis[k] + map[k][i]; 107 } 108 } 109 } 110 return; 111 }
接下来是Floyd解法,比Dijkstra解法耗时长,但是优势在于代码编写简单
1 #include <stdio.h> 2 #include <string.h> 3 #define N 151 4 #define NAME 31 5 #define INF 9999999 6 7 int map[N][N]; 8 char name[N][NAME]; 9 int na; //站点的个数 10 int n; //道路的个数 11 12 void Init(); //初始化 13 14 void Read(); //输入 15 16 int Count(char s[]); //计算字符串对应的编号 17 18 void Floyd(); 19 20 int main() 21 { 22 while (~scanf("%d", &n)) 23 { 24 if (n == -1) break; 25 Init(); 26 Read(); 27 Floyd(); 28 if (strcmp(name[1], name[0]) == 0) 29 { 30 printf("0 "); 31 continue; 32 } 33 printf("%d ", map[0][1] == INF ? -1 : map[0][1]); 34 } 35 return 0; 36 } 37 38 void Init() //初始化 39 { 40 int i, j; 41 for (i=0; i<N; ++i) 42 { 43 for (j=0; j<N; ++j) 44 { 45 map[i][j] = INF; 46 } 47 } 48 scanf("%s %s", name[0], name[1]); 49 na = 2; 50 return; 51 } 52 53 void Read() //输入 54 { 55 int i; 56 char sa[NAME], sb[NAME]; 57 int a, b, c; 58 for (i=0; i<n; ++i) 59 { 60 scanf("%s %s %d", sa, sb, &c); 61 a = Count(sa); 62 b = Count(sb); 63 map[a][b] = map[b][a] = c; 64 } 65 return; 66 } 67 68 int Count(char s[]) //计算字符串对应的编号 69 { 70 int i; 71 for (i=0; i<na; ++i) 72 { 73 if (strcmp(name[i], s) == 0) 74 { 75 return i; 76 } 77 } 78 strcpy(name[na++], s); 79 return (na - 1); 80 } 81 82 void Floyd() 83 { 84 int i, j, k; 85 for (k=0; k<na; ++k) 86 { 87 for (i=0; i<na; ++i) 88 { 89 for (j=0; j<na; ++j) 90 { 91 if (map[i][j] > map[i][k] + map[k][j]) 92 { 93 map[i][j] = map[i][k] + map[k][j]; 94 } 95 } 96 } 97 } 98 return; 99 }