Description
In the year 2163, wormholes were discovered. A wormhole is a subspace tunnel through space and time connecting two star systems. Wormholes have a few peculiar properties:
All wormholes have a constant time difference between their end points. For example, a specific wormhole may cause the person travelling through it to end up 15 years in the future. Another wormhole may cause the person to end up 42 years in the past.
A brilliant physicist, living on earth, wants to use wormholes to study the Big Bang. Since warp drive has not been invented yet, it is not possible for her to travel from one star system to another one directly. This can be done using wormholes, of course.
The scientist wants to reach a cycle of wormholes somewhere in the universe that causes her to end up in the past. By travelling along this cycle a lot of times, the scientist is able to go back as far in time as necessary to reach the beginning of the universe and see the Big Bang with her own eyes. Write a program to find out whether such a cycle exists.
2 3 3 0 1 1000 1 2 15 2 1 -42 4 4 0 1 10 1 2 20 2 3 30 3 0 -60
possible not possible
题目大意:
有很多单向虫洞,经过这个虫洞后穿越到过去或者是未来,一个科学家想要研究宇宙大爆炸(Big Bang)让你判断有没有可能回到过去亲眼目睹宇宙大爆炸。
思路:
既然是要回到过去,肯定需要两个点,从a点到b点,在从b点回到a点之后,穿越到了过去,然后无限循环的走这两个点,总有可能走在宇宙大爆炸前。可以把变化的时间当成是两个点之间的距离。这样就是关键找每两个点之间的距离,然后比较从自身到自身的是否回到了过去。
这里运用到一个方便的算法————Floyd 算法;
思想就是用二维数组存储各个路径,然后判断当每个点都为其他的顶点的中间顶点(比如: 从2到3的有一条路,然后从2到1 从1 到3也有条路径 判断当1为中间顶点时两条路谁更短一些然后更新即可),中间顶点也可能不唯一,然后判断经过中间节点和不经过中间节点两个路的长度,每次更新到最短。
代码如下:
#include<stdio.h> #include<string.h> #include<cmath> #include<algorithm> #include<iostream> #define INF 0x1f1f1f1f using namespace std; int s[1010][1010]; int main() { int i, j, k, m, n, t, x, y, time; scanf("%d",&t); while(t--) { scanf("%d%d",&n,&m); memset(s, INF, sizeof(s)); for(i = 0; i < m; i++) { scanf("%d%d%d",&x,&y,&time); s[x][y] = time; } for(i = 0; i < n; i++)// 以i为中间顶点 for(j = 0; j < n; j++) if(s[j][i] < INF) // 如果j到i没有路,没有必要判断下面 for(k = 0; k < n; k++) { if(s[i][k] < INF) { if(s[i][k] + s[j][i] < s[j][k]) // 判断经过中间顶点路径和不经过的大小 s[j][k] = s[i][k] + s[j][i]; //更新路径 } } int flag = 0; for(i = 0; i < n; i++) { for(j = 0; j < n; j++) { if(s[i][j] < INF && s[j][i] < INF) { if(s[i][j] + s[j][i] < 0)//判断是否有条回路能否走到过去。 { flag = 1; // 如果有回路标记 break; } } } if(flag) break; } if(flag) printf("possible\n"); else printf("not possible\n"); } return 0; }