负环
负环
什么是负环
顾名思义 就是一个所有边的边权和为负数的环
出现负环会怎么样
一旦出现负环,那么s到t的最短路就会不断地走这个环。那么每条最短路每经过一次负环,最短路就会减少一点。
如果走无数次,那么也就不存在最短路。当然每个点经过的次数不超过1
怎么判负环
这里我们讲比较常用的SPFA判负环(虽然SPFA他死了)。如果存在负环,那么最短路就会不断地缩小。我们可以利用
这个特性 在SPFA中每个点最多被其他n-1个点更新一次。如果被更新了n次,那么说明存在负环。
模板——>负环
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<queue> 5 #include<cstring> 6 using namespace std; 7 int t,n,m,tot,u,v,w; 8 int head[2100],dis[2100],num[2100]; 9 bool in[2100]; 10 struct node{ 11 int to; 12 int w; 13 int net; 14 }e[6100]; 15 void add(int x,int y,int w){ 16 tot++; 17 e[tot].to = y; 18 e[tot].w = w; 19 e[tot].net = head[x]; 20 head[x] = tot; 21 } 22 bool spfa(){ 23 memset(dis,0x7f,sizeof(dis)); 24 memset(in,0,sizeof(in)); 25 memset(num,0,sizeof(num)); 26 queue<int> q; 27 q.push(1); dis[1] = 0; 28 num[1] = 1,in[1] = 1; 29 while(!q.empty()){ 30 int t = q.front(); 31 q.pop(); 32 in[t] = 0; 33 for(int i = head[t]; i; i = e[i].net){ 34 int to = e[i].to; 35 if(dis[to] > dis[t] + e[i].w){ 36 dis[to] = dis[t] + e[i].w; 37 num[to]++; 38 if(num[to] > n) return 1; 39 if(in[to] == 0){ 40 q.push(to); 41 in[to] = 1; 42 } 43 } 44 } 45 } 46 return 0; 47 } 48 int main(){ 49 scanf("%d",&t);
50 while(t--){ 51 scanf("%d%d",&n,&m); 52 tot = 0; 53 memset(head,0,sizeof(head)); 54 for(int i = 1; i <= m; i++){ 55 scanf("%d%d%d",&u,&v,&w);
56 if(w >= 0){ 57 add(u,v,w); 58 add(v,u,w); 59 } 60 else add(u,v,w); 61 } 62 if(spfa()) cout<<"YE5"<<endl; 63 else cout<<"N0"<<endl; 64 } 65 }
习题 虫洞