求负环的常用方法,基于spfa:
①统计每个点入队的次数,如果某个点入队n次,则说明存在负环。
②统计当前每个点的最短路中所包含的边数,如果某点的最短路所包含的边数大于等于n,则说明存在负环。
通常用第二种方法。
1 bool spfa() 2 { 3 memset(dist, 0, sizeof dist); 4 memset(cnt, 0, sizeof cnt); 5 memset(st, 0, sizeof st); 6 7 int hh = 0, tt = 0; 8 for (int i = 1; i <= n; i ++ ) 9 { 10 q[tt ++ ] = i; 11 st[i] = true; 12 } 13 14 while (hh != tt) 15 { 16 int t = q[hh ++ ]; 17 if (hh == N) hh = 0; 18 st[t] = false; 19 20 for (int i = h[t]; ~i; i = ne[i]) 21 { 22 int j = e[i]; 23 if (dist[j] > dist[t] + w[i]) 24 { 25 dist[j] = dist[t] + w[i]; 26 cnt[j] = cnt[t] + 1; 27 if (cnt[j] >= n) return true; 28 if (!st[j]) 29 { 30 q[tt ++ ] = j; 31 if (tt == N) tt = 0; 32 st[j] = true; 33 } 34 } 35 } 36 } 37 38 return false; 39 }
\frac{\sum_{i = 1}^{n}f_{i}}{\sum_{i = 1}^{n}t_{i}} > Mid