POJ 3259 Wormholes(SPFA判负环)
题目链接:http://poj.org/problem?id=3259
题目大意是给你n个点,m条双向边,w条负权单向边。问你是否有负环(虫洞)。
这个就是spfa判负环的模版题,中间的cnt数组就是记录这个点松弛进队的次数,次数超过点的个数的话,就说明存在负环使其不断松弛。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <queue> 5 using namespace std; 6 const int MAXN = 1e3 + 5; 7 const int INF = 1e9; 8 struct data { 9 int next , to , cost; 10 }edge[MAXN * 10]; 11 int head[MAXN] , d[MAXN] , cnt[MAXN] , cont; 12 bool vis[MAXN]; 13 14 void init(int n) { 15 for(int i = 1 ; i <= n ; i++) { 16 d[i] = INF; 17 cnt[i] = 0; 18 head[i] = -1; 19 vis[i] = false; 20 } 21 cont = 0; 22 } 23 24 inline void add(int u , int v , int cost) { 25 edge[cont].next = head[u]; 26 edge[cont].to = v; 27 edge[cont].cost = cost; 28 head[u] = cont++; 29 } 30 31 bool spfa(int s , int n) { 32 d[s] = 0; 33 queue <int> que; 34 while(!que.empty()) { 35 que.pop(); 36 } 37 que.push(s); 38 while(!que.empty()) { 39 int temp = que.front(); 40 que.pop(); 41 vis[temp] = false; 42 for(int i = head[temp] ; ~i ; i = edge[i].next) { 43 int v = edge[i].to; 44 if(d[v] > d[temp] + edge[i].cost) { 45 d[v] = d[temp] + edge[i].cost; 46 if(!vis[v]) { 47 que.push(v); 48 vis[v] = true; 49 cnt[v]++; 50 if(cnt[v] >= n) 51 return true; 52 } 53 } 54 } 55 } 56 return false; 57 } 58 59 int main() 60 { 61 int n , m , c , u , v , cost , t; 62 scanf("%d" , &t); 63 while(t--) { 64 scanf("%d %d %d" , &n , &m , &c); 65 init(n); 66 while(m--) { 67 scanf("%d %d %d" , &u , &v , &cost); 68 add(u , v , cost); 69 add(v , u , cost); 70 } 71 while(c--) { 72 scanf("%d %d %d" , &u , &v , &cost); 73 add(u , v , -cost); 74 } 75 if(spfa(1 , n)) { 76 printf("YES\n"); 77 } 78 else { 79 printf("NO\n"); 80 } 81 } 82 }