这是一道不错的最短路题目,半水不水的题,还是需要动脑思考一下的。题意:琪琪想要去拜访她的朋友,但是这货容易晕车,所以要找一个花费时间最少的路线。现在给你路线图,让你找出从她家附近的起点站(可以有多个)到朋友家附近的终点站(只有一个)花费时间最少的路线。各个站点的编号从1到n。
我的解题思路:首先是输入站点数量,路线数量(在两个站点之间可以有多条路线)和终点;然后是各个路线的信息(起点终点以及耗时);最后再输入起点的个数和起点。由于站点数量最多可以达到1000,因此Floyd算法是不行的了(事实上我一开始就用这个写,TLE了)。我们换个思路,用Dijkstra啊!有几个起点就用几次Dijkstra。恩,这么做是没什么错,只要起点的数量不是很接近站点的数量,那么多多少少的确有所优化(没用此方法提交过)。但是我们可以有一种更加精明的解法啊,那就是把终点看做起点,起点看做终点,这样的话用一次Dijkstra就可以了,省时省力有省心啊有木有。可见,多思考一下别的解法还是有用的。
注意:本题为单向图。那么,起点看做终点,终点看做起点时要进行反向构图。
接下来是我的解题代码:Dijkstra解法
1 #include <stdio.h> 2 #define N 1001 3 #define INF 999999 4 5 int map[N][N]; 6 int dis[N]; //在本题中代表从终点s到编号为下标的点的时间 7 int flag[N]; //标志变量 8 int n, m, s; 9 10 void Init(); //初始化 11 12 void Read(); //图信息的输入 13 14 void Dijkstra(); 15 16 void DataProcess(); //起点的输入以及答案的计算 17 18 int main() 19 { 20 while (~scanf("%d %d %d", &n, &m, &s)) 21 { 22 Init(); 23 Read(); 24 Dijkstra(); 25 DataProcess(); 26 } 27 return 0; 28 } 29 30 void Init() //初始化 31 { 32 int i, j; 33 for (i=1; i<=n; ++i) 34 { 35 for (j=1; j<=n; ++j) 36 { 37 map[i][j] = i == j ? 0 : INF; 38 } 39 dis[i] = INF; 40 flag[i] = 0; 41 } 42 return; 43 } 44 45 void Read() //图信息的输入 46 { 47 int i; 48 int a, b, c; 49 for (i=0; i<m; ++i) 50 { 51 scanf("%d %d %d", &a, &b, &c); 52 if (map[b][a] > c) //处理重边问题 53 { 54 map[b][a] = c; //反向构图 55 } 56 } 57 return; 58 } 59 60 void Dijkstra() 61 { 62 int i, j, k; 63 int min; 64 dis[s] = 0; //设终点为起点 65 for (i=1; i<=n; ++i) 66 { 67 min = INF; 68 for (j=1; j<=n; ++j) 69 { 70 if (flag[j] == 0 && dis[j] < min) 71 { 72 min = dis[k = j]; 73 } 74 } 75 flag[k] = 1; 76 for (j=1; j<=n; ++j) 77 { 78 if (flag[j] == 0 && dis[j] > dis[k] + map[k][j]) 79 { 80 dis[j] = dis[k] + map[k][j]; 81 } 82 } 83 } 84 return; 85 } 86 87 void DataProcess() //起点的输入以及答案的计算 88 { 89 int i, w, x; 90 int ans = INF; 91 scanf("%d", &w); 92 for (i=0; i<w; ++i) 93 { 94 scanf("%d", &x); 95 if (ans > dis[x]) 96 { 97 ans = dis[x]; 98 } 99 } 100 printf("%d ", ans == INF ? -1 : ans); 101 return; 102 }