题目链接:http://poj.org/problem?id=1122 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=53
题目大意:
给定一个有向图,一个终点S,求多个点到这个点S的最短距离和对应的路径,把最短路排序后输出。
题目思路:
点的范围是20.可以一个一个用Dijkstra。。唯一的新意就是有多个点还需要按照路径长度排序,同时还要输出对应的路径,考的就是代码能力。用结构体存就可以。注意是有向图,开始就以为是无向图,怎么算最短路都不对。。赶脚这题不难,没什么思维难度,但是做OJ上这题的人却比较少,可能有一个原因,题目比较长,然后读完题目之后觉得没什么意思就不做了。。很简单的一个东西搞这么长的题目,也许就是考的读题吧。。貌似如果不是看的书上的翻译,我也没耐心读题。。。唉,读题确实是关键的一关。
然后这道题目,Poj上是单case,比较好过,然后数据也貌似比较弱,因为是单case,所以有一个输入的细节就特别好处理。开始Poj一下就过了,还沾沾自喜,结果把单case换成多case的时候,在zoj上交就Segmentation Fault……原来我最初处理输入个数不确定的数字的时候用了 while(~scanf())这种方法,很显然,这货只适用于单case。然后就想,该怎么处理这种输入数字个数不确定的输入呢?看了网上的一个思路,http://blog.csdn.net/yzldw333/article/details/7858172 哈哈,原来这么简单,就是以前做过的么,按照字符串处理就行了,,,好吧,,原来自己就是怕麻烦,这种方法想都没想。。然后就改了,,还是Segmentation Fault……继续调试,查错。。忍不住看了一下别人的代码,http://www.cnblogs.com/372465774y/archive/2012/11/19/2777552.html 一个注释提示了我,“这题给的字符真的是:\t ' '”好吧……我还真没注意到,虽然读题的时候注意到了,但是写代码的时候就想当然地只考虑空格,,像以前那样……思维定式啊。。然后就过了。。
Segmentation Fault的原因是访问了非法内存,在新的OJ上如果用的是Linux的话,归在Runtime Error一类里面。多谢zsl!
Poj代码:
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 23 const int MAX = 20; 24 int edge[MAX][MAX], n, dist[MAX], path[MAX], end; 25 bool S[MAX]; 26 typedef struct Fire { 27 int street[MAX], len, start, E; 28 bool operator < (const Fire &other) const { 29 return len < other.len; 30 } 31 }Fire; 32 Fire fire[MAX]; 33 void Dijkstra(int u0, Fire &su) { 34 int i, j, k, u, Min; 35 for (i = 1; i <= n; ++i) { 36 dist[i] = edge[u0][i]; S[i] = false; 37 if (i != u0 && edge[u0][i] != MAXN) path[i] = u0; 38 else path[i] = -1; 39 } 40 S[u0] = true; path[u0] = -1; 41 for (i = 1; i < n; ++i) { 42 Min = MAXN; u = u0; 43 for (j = 1; j <= n; ++j) { 44 if (S[j] == false && dist[j] < Min) { 45 Min = dist[j]; u = j; 46 } 47 } 48 S[u] = true; 49 for (j = 1; j <= n;++j) { 50 if (S[j] == false && edge[u][j] != MAXN) { 51 int tmp = edge[u][j] + dist[u]; 52 if (tmp < dist[j]) { 53 dist[j] = tmp; path[j] = u; 54 } 55 } 56 } 57 if (u == end) break; 58 } 59 k = 0; su.street[k] = end; int ho = path[end]; 60 while (ho != -1) { 61 su.street[++k] = ho; ho = path[ho]; 62 } 63 su.E = k; 64 su.len = dist[end]; 65 } 66 int main(void){ 67 #ifndef ONLINE_JUDGE 68 freopen("poj1122.in", "r", stdin); 69 #endif 70 int i, j; 71 while (~scanf("%d", &n)) { 72 for (i = 1; i <= n; ++i) { 73 for (j = 1; j <= n; ++j) { 74 scanf("%d", &edge[i][j]); 75 if (edge[i][j] == -1) edge[i][j] = MAXN; 76 } 77 } 78 scanf("%d", &end); 79 printf("Org\tDest\tTime\tPath\n"); 80 int cnt= 0, start; 81 while (~scanf("%d", &start)) { 82 fire[cnt].start = start; 83 Dijkstra(start, fire[cnt]); 84 cnt++; 85 } 86 sort(fire, fire+cnt); 87 for (i = 0; i < cnt; ++i) { 88 printf("%d\t%d\t%d\t", fire[i].start, end, fire[i].len); 89 for (j = fire[i].E; j > 0; --j) { 90 printf("%d\t", fire[i].street[j]); 91 } 92 printf("%d\n", fire[i].street[0]); 93 } 94 } 95 96 return 0; 97 }
Zoj代码: 注意第86行到96行
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 23 const int MAX = 30; 24 int edge[MAX][MAX], n, dist[MAX], path[MAX], end; 25 bool S[MAX]; 26 typedef struct Fire { 27 int street[MAX], len, start, E; 28 bool operator < (const Fire &other) const { 29 return len < other.len; 30 } 31 }Fire; 32 Fire fire[MAX]; 33 void Dijkstra(int u0, Fire &su) { 34 int i, j, k, u, Min; 35 for (i = 1; i <= n; ++i) { 36 dist[i] = edge[u0][i]; S[i] = false; 37 if (i != u0 && edge[u0][i] != MAXN) path[i] = u0; 38 else path[i] = -1; 39 } 40 S[u0] = true; path[u0] = -1; 41 for (i = 1; i < n; ++i) { 42 Min = MAXN; u = u0; 43 for (j = 1; j <= n; ++j) { 44 if (S[j] == false && dist[j] < Min) { 45 Min = dist[j]; u = j; 46 } 47 } 48 S[u] = true; 49 for (j = 1; j <= n;++j) { 50 if (S[j] == false && edge[u][j] != MAXN) { 51 int tmp = edge[u][j] + dist[u]; 52 if (tmp < dist[j]) { 53 dist[j] = tmp; path[j] = u; 54 } 55 } 56 } 57 if (u == end) break; 58 } 59 k = 0; su.street[k] = end; int ho = path[end]; 60 while (ho != -1) { 61 su.street[++k] = ho; ho = path[ho]; 62 } 63 su.E = k; 64 su.len = dist[end]; 65 } 66 int main(void){ 67 #ifndef ONLINE_JUDGE 68 freopen("poj1122.in", "r", stdin); 69 #endif 70 int i, j, T; 71 scanf("%d", &T); 72 for (int I = 0; I < T; ++I) 73 { 74 scanf("%d", &n); 75 for (i = 1; i <= n; ++i) { 76 for (j = 1; j <= n; ++j) { 77 scanf("%d", &edge[i][j]); 78 if (edge[i][j] == -1) edge[i][j] = MAXN; 79 } 80 } 81 scanf("%d", &end); 82 printf("Org\tDest\tTime\tPath\n"); 83 int cnt= 0, start; 84 getchar(); char ch[100]; gets(ch); 85 int len = strlen(ch); 86 for (i = 0; i < len; ++i) { 87 while (!isdigit(ch[i])) i++; // 果然不仅仅有空格!! 88 start = 0; 89 while (isdigit(ch[i]) && i < len) { 90 start = start * 10 + (ch[i]-'0'); 91 i++; 92 } 93 fire[cnt].start = start; 94 Dijkstra(start, fire[cnt]); 95 cnt++; 96 } 97 sort(fire, fire+cnt); 98 for (i = 0; i < cnt; ++i) { 99 printf("%d\t%d\t%d\t", fire[i].start, end, fire[i].len); 100 for (j = fire[i].E; j > 0; --j) { 101 printf("%d\t", fire[i].street[j]); 102 } 103 printf("%d\n", fire[i].street[0]); 104 } 105 if (I != T-1) printf("\n"); 106 } 107 108 return 0; 109 }
赶脚还是要认真读题啊,像今天这种细节。。就是一个致命的错误