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 }

 

posted @ 2021-10-21 16:37  Modest-Hamilton  阅读(31)  评论(0)    收藏  举报