SPFA判断负环
【题目描述】
给定一个 n 个点 m 条边的有向图,图中可能存在重边和自环, 边权可能为负数。
请你判断图中是否存在负权回路。
【输入格式】
第一行包含整数 n 和 m。
接下来 mm 行每行包含三个整数 x,y,z,表示存在一条从点 x 到点 y 的有向边,边长为 z。
【输出格式】
如果图中存在负权回路,则输出 Yes,否则输出 No。
【数据范围】
1≤n≤2000,
1≤m≤10000,
图中涉及边长绝对值均不超过 10000。
【输入样例】
3 3
1 2 -1
2 3 4
3 1 -4
【输出样例】
Yes
开个cnt数组计算一下每个最短路的点数即可,由于负环不一定从1能走到,所以需要把所有可能是负环的起点加入到队列里面。
1 #include <iostream> 2 #include <queue> 3 #include <string.h> 4 using namespace std; 5 const int N = 100009; 6 int e[N],h[N],ne[N],v[N],idx; 7 int dist[N],st[N],cnt[N]; 8 int n,m; 9 queue<int> que; 10 void add(int a,int b,int c) 11 { 12 e[idx] = b; 13 v[idx] = c; 14 ne[idx] = h[a]; 15 h[a] = idx++; 16 } 17 18 bool spfa() 19 { 20 while(!que.empty()) 21 { 22 int p = que.front(); 23 que.pop(); 24 st[p] = 0; 25 for(int i = h[p];i != -1;i = ne[i]) 26 { 27 int j = e[i]; 28 if(dist[j] > dist[p] + v[i]) 29 { 30 dist[j] = dist[p] + v[i]; 31 cnt[j] = cnt[p] + 1; 32 if(cnt[j] >= n) 33 return true; 34 if(!st[j]) 35 { 36 que.push(j); 37 st[j] = 1; 38 } 39 } 40 } 41 } 42 return false; 43 } 44 45 int main() 46 { 47 memset(h,-1,sizeof h); 48 cin >> n >> m; 49 while(m--) 50 { 51 int a,b,c; 52 cin >> a >> b >> c; 53 add(a,b,c); 54 if(c < 0) 55 que.push(a); 56 } 57 if(spfa()) 58 cout << "Yes" << endl; 59 else 60 cout << "No" << endl; 61 return 0; 62 }

浙公网安备 33010602011771号