昆虫洞
昆虫洞
Problem Description
当农场主John在开垦他的农场时,发现了许多奇怪的昆虫洞。这些昆虫洞是单向的,并且可以从入口到出口,并且使得时间倒退一段。John的每个农场包含N(1≤N≤500)块地,编号从1~N,这N快地之间有M(1≤M≤2500)条路、W(1≤W≤200)个昆虫洞。
因为John是一个狂热的时间旅行迷,他想尝试着做这样一件事:从某块地出发,通过一些路径和昆虫洞,返回出发点,并且时间早于出发时间,这样或许他可以遇到他自己。试帮助John判断是否可行。他将提供他的F(1≤F≤5)个农场的完整地图。每条路走完所需时间不超过10 000秒,每个昆虫洞倒退的事件也不超过10 000秒。
因为John是一个狂热的时间旅行迷,他想尝试着做这样一件事:从某块地出发,通过一些路径和昆虫洞,返回出发点,并且时间早于出发时间,这样或许他可以遇到他自己。试帮助John判断是否可行。他将提供他的F(1≤F≤5)个农场的完整地图。每条路走完所需时间不超过10 000秒,每个昆虫洞倒退的事件也不超过10 000秒。
Input
输入文件第1行为一个整数F,表示F个测试数据,每个测试数据描绘了一个农场。接下来是F个农场的数据。
每个农场的第1行为3个整数:N、M和W。第2行至第M+1行,每行为3个整数:S、E和T,表示一条从S到E的双向路径,通过这条路径所需事件为T秒,两块地之间至多有一条路。第M+2~第M+W+1行,每行3个整数:S、E和T,表示从S到E的一条单向路,通过这条路使得时间倒退T秒。
每个农场的第1行为3个整数:N、M和W。第2行至第M+1行,每行为3个整数:S、E和T,表示一条从S到E的双向路径,通过这条路径所需事件为T秒,两块地之间至多有一条路。第M+2~第M+W+1行,每行3个整数:S、E和T,表示从S到E的一条单向路,通过这条路使得时间倒退T秒。
Output
对每个测试数据,如果John能实现自己的目标,输出”YES”;否则输出”NO”。
Sample Input
2 3 3 1 1 2 2 1 3 4 2 3 1 3 1 3 3 2 1 1 2 3 2 3 4 3 1 8
Sample Output
NO YES
解释:
这个题目很容易看出是一个判断有没有负环的题目,我用的是SPFA算法,百度一下,然后学一下这个算法,这个题相当于模板题。然后测试数据是,最后一组测试用例没有换行。是真滴gay.
1 #include<bits/stdc++.h> 2 3 using namespace std; 4 const int N = 5210; 5 const int INF = 0xFFFFFFF; 6 7 struct edge{ 8 int v, w, next; 9 }edges[N]; 10 11 int dist[N], num[N], frist[N]; 12 bool vis[N]; 13 int n, m, w; 14 int e_sums; 15 16 int Scan() { //输入挂 17 int res = 0, ch, flag = 0; 18 if ((ch = getchar()) == '-') 19 flag = 1; 20 else if (ch >= '0' && ch <= '9') 21 res = ch - '0'; 22 while ((ch = getchar()) >= '0' && ch <= '9') 23 res = res * 10 + ch - '0'; 24 return flag ? -res : res; 25 } 26 27 void Out (int a) { //输出挂 28 if (a > 9) 29 Out(a / 10); 30 putchar(a % 10 + '0'); 31 } 32 33 void addEdge (int u, int v, int w) { 34 edges[e_sums].v = v; 35 edges[e_sums].w = w; 36 edges[e_sums].next = frist[u]; 37 frist[u] = e_sums++; 38 } 39 40 bool spfa() { 41 queue<int> que; 42 dist[1] = 0; 43 vis[1] = true; 44 que.push(1); 45 num[1]++; 46 while (que.size()) { 47 int u = que.front(); 48 que.pop(); 49 vis[u] = false; 50 for (int i = frist[u]; i != -1; i = edges[i].next) { 51 int v = edges[i].v; 52 if (dist[v] > dist[u] + edges[i].w) { 53 dist[v] = dist[u] + edges[i].w; 54 if ( !vis[v] ) { 55 vis[v] = true; 56 que.push(v); 57 num[v]++; 58 if (num[v] > n) { 59 return true; 60 } 61 } 62 } 63 } 64 } 65 return false; 66 } 67 68 69 int main() { 70 int t; 71 //scanf("%d", &t); 72 t = Scan(); 73 int gz = 1; 74 while (t--) { 75 if (!gz)putchar('\n'); 76 gz = 0; 77 e_sums = 0; 78 memset(frist, -1, sizeof(frist)); 79 memset(vis, false, sizeof(vis)); 80 memset(num, 0, sizeof(num)); 81 82 //scanf("%d %d %d", &n, &m, &w); 83 n = Scan(), m = Scan(), w = Scan(); 84 for (int i = 1; i <= n; i++) { 85 dist[i] = INF; 86 } 87 88 89 int x, y, z; 90 for (int i = 0; i < m; i++) { 91 //scanf("%d %d %d", &x, &y, &z); 92 x = Scan(), y = Scan(), z = Scan(); 93 addEdge(x, y, z); 94 addEdge(y, x, z); 95 } 96 97 for (int i = 0; i < w; i++) { 98 //scanf("%d %d %d", &x, &y, &z); 99 x = Scan(), y = Scan(), z = Scan(); 100 addEdge(x, y, -z); 101 } 102 103 if ( spfa() ) { 104 printf("YES"); 105 } else { 106 printf("NO"); 107 } 108 } 109 return 0; 110 }
感觉我同学,强行试出来,这个格式错误的解决办法,这才是真大佬。