POJ3259 Wormholes 【spfa判负环】
作者:互联网
题目链接:http://poj.org/problem?id=3259
WormholesTime Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions:75598 | Accepted: 28136 |
Description
While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..N, M (1 ≤ M ≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.
As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .
To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.
Input
Line 1: A single integer, F. F farm descriptions follow.Line 1 of each farm: Three space-separated integers respectively: N, M, and W
Lines 2..M+1 of each farm: Three space-separated numbers (S, E, T) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path.
Lines M+2..M+W+1 of each farm: Three space-separated numbers (S, E, T) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds. 题目大意:n 个点, m 条双向边,代表经过所需的时间,w 条单向边,代表经过所减少的时间。问该图中是否存在负环。 思路: 1.简单的判环,用spfa即可,在不存在环的情况下,任意点在进行路径松弛时,最多被其他的点更新一次。那么任意点的最多入队次数只能是 n 次。当存在任何一点的入队次数大于顶点数n,即说明存在环。 2.判负环,即路径往小松弛。判正环时,即路径往大更新。注意dis数组初始化即可。 代码如下:
1 #include<stdio.h> 2 #include<queue> 3 #include<string.h> 4 #define mem(a, b) memset(a, b, sizeof(a)) 5 const int MAXN = 550; 6 const int MAXM = 3000; 7 const int inf = 0x3f3f3f3f; 8 using namespace std; 9 10 int n, m, k; //n个点 m条双向边 k个虫洞(单向边) 11 int head[MAXN], cnt; 12 int vis[MAXN], num[MAXN];//num表示第i个点的入队次数 用来判断负环是否存在 13 int dis[MAXN], flag; 14 queue<int> Q; 15 16 struct Edge 17 { 18 int to, next, w; 19 }edge[2 * MAXM]; 20 21 void add(int a, int b, int c) 22 { 23 cnt ++; 24 edge[cnt].to = b; 25 edge[cnt].w = c; 26 edge[cnt].next = head[a]; 27 head[a] = cnt; 28 } 29 30 void spfa(int st) 31 { 32 while(!Q.empty()) Q.pop(); 33 mem(vis, 0), mem(dis, inf), mem(num, 0); 34 Q.push(st); 35 vis[st] = 1; 36 num[st] = 1; 37 dis[st] = 0; 38 while(!Q.empty()) 39 { 40 int a = Q.front(); 41 Q.pop(); 42 vis[a] = 0; 43 for(int i = head[a]; i != -1; i = edge[i].next) 44 { 45 int to = edge[i].to; 46 if(dis[to] > dis[a] + edge[i].w) 47 { 48 dis[to] = dis[a] + edge[i].w; 49 if(!vis[to]) 50 { 51 vis[to] = 1; 52 Q.push(to); 53 num[to] ++; 54 if(num[to] > n) 55 { 56 flag = 1; 57 break; 58 } 59 } 60 } 61 } 62 if(flag) 63 break; 64 } 65 if(flag) 66 printf("YES\n"); 67 else 68 printf("NO\n"); 69 } 70 71 int main() 72 { 73 int T; 74 scanf("%d", &T); 75 while(T --) 76 { 77 cnt = 0, flag = 0, mem(head, -1); 78 scanf("%d%d%d", &n, &m, &k); 79 for(int i = 1; i <= m; i ++) 80 { 81 int a, b, c; 82 scanf("%d%d%d", &a, &b, &c); 83 add(a, b, c); 84 add(b, a, c); 85 } 86 for(int i = 1; i <= k; i ++) 87 { 88 int a, b, c; 89 scanf("%d%d%d", &a, &b, &c); 90 add(a, b, -c); 91 } 92 spfa(1); 93 } 94 return 0; 95 }POJ3259
标签:cnt,num,POJ3259,int,vis,判负,spfa,edge,dis 来源: https://www.cnblogs.com/yuanweidao/p/11479589.html