标签:
题意:
有N块地,M条无向路,W条有向路,无向路的权值为正,有向路的权值为负,问自否存在负环。
思路:
用邻接表保存图,使用SPFA+SLF优化。
判断是否存在负环时,另设一个数组用来记录从源点到各个点的最短路径所经过的路径条数,若路径条数大于等于N(点的个数),说明存在负环。(仔细想想为什么)
AC代码,16ms…
1 #include <cstdio> 2 #include <string.h> 3 #include <deque> 4 using namespace std; 5 const int N = 510, M = 5500, INF = 0x3f3f3f3f; 6 int u[M], v[M], weigth[M], Next[M], first[N], D[N]; 7 bool SPFA(int n) 8 { 9 int t, num[N] = {0}; 10 bool cnt[N] = {0}; 11 memset(D, INF, sizeof(D)); 12 D[0] = 0; 13 cnt[0] = true; 14 deque<int> dq; 15 dq.push_front(0); 16 while(!dq.empty()) 17 { 18 t = dq.front(); 19 dq.pop_front(); 20 for(int x=first[t]; ~x; x=Next[x]) 21 { 22 if(D[v[x]] > D[u[x]] + weigth[x]) 23 { 24 D[v[x]] = D[u[x]] + weigth[x]; 25 num[v[x]] = num[u[x]] + 1; 26 if(num[v[x]] >= n) 27 return false; 28 if(!cnt[v[x]]) 29 { 30 if(!dq.empty() && D[v[x]] < D[dq.front()]) 31 dq.push_front(v[x]); 32 else 33 dq.push_back(v[x]); 34 cnt[v[x]] = true; 35 } 36 } 37 } 38 cnt[t] = false; 39 } 40 return true; 41 } 42 int main(void) 43 { 44 int kase, n, m, w, num; 45 scanf("%d", &kase); 46 while(kase--) 47 { 48 memset(first, -1, sizeof(first)); 49 scanf("%d %d %d", &n, &m, &w); 50 num = 0; 51 for(int i=0; i<m; ++i) 52 { 53 scanf("%d %d %d", u+num, v+num, weigth+num); 54 --u[num], --v[num]; 55 Next[num] = first[u[num]]; 56 first[u[num]] = num++; 57 u[num] = v[num-1], v[num] = u[num-1], weigth[num] = weigth[num-1]; 58 Next[num] = first[u[num]]; 59 first[u[num]] = num++; 60 } 61 for(int i=0; i<w; ++i) 62 { 63 scanf("%d %d %d", u+num, v+num, weigth+num); 64 --u[num], --v[num], weigth[num] = 0 - weigth[num]; 65 Next[num] = first[u[num]]; 66 first[u[num]] = num++; 67 } 68 printf("%s\n", SPFA(n) ? "NO" : "YES"); 69 } 70 }
标签:
原文地址:http://www.cnblogs.com/gwtan/p/4780447.html