负环及其应用

什么是负环?
顾名思义,就是一个所有边的边权和为负数的环。

出现负环会怎么样?
我们知道,一般情况下,图上的最短路都是确定的。但是一旦图上有一个负环, s s s t t t 的最短路就会不远千里的去覆盖上这个环(只要能够到达),并且不厌其烦的走上一遍又一遍。由于负环的边权和是负的,并且它是一个环,也就是说走一遍和走无数遍都停留在进入的那个点。那么最短路每经过一次这个负环,这个费用都会缩小一点,如果经过了无数次,也就是无穷小,也就是不存在最短路。当然这里有一个限定,就是每个点经过的次数不能超过 1 1 1 次。

怎么判定负环?

根据负环的定义,我们知道在有负环的图中不存在最短路,因为你可以绕着负环一直跑,而你的路径和却会越来越少!

所以如果我们在有负环的图上跑SPFA,会陷入死循环的!

正因为这点,所以可以用SPFA来判断负环。

c n t [ x ] cnt[x] cnt[x] 表示 x x x 这个节点入队了几次(也就是 x x x 这个节点的最短路被更新了几次),若图中有 n n n 个节点,那么每个节点最多 n − 1 n−1 n1 次入队,当入队次数,即 c n t [ x ] ≥ n cnt[x]≥n cnt[x]n 时,退出循环,并确定图中有负环。

模板题 代码(贺的)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
const int N = 20010, M = 30010;
int t, n, m, tot, head[N], ver[M << 1], nex[M << 1], edge[M << 1], dis[N], vis[N], cnt[N], flag;
inline void add (int x, int y, int z) {
	ver[++ tot] = y;
	edge[tot] = z;
	nex[tot] = head[x];
	head[x] = tot;
}
inline void spfa () {
	queue <int> q;
	q.push(1);
	vis[1] = 1;
	dis[1] = 0;
	while (!q.empty()) {
		int x = q.front();
		q.pop();
		vis[x] = 0;
		for (int i = head[x]; i; i = nex[i]) {
			int y = ver[i], w = edge[i];
			if (dis[y] > dis[x] + w) {
				dis[y] = dis[x] + w;
				if (!vis[y]) {
					q.push(y);
					vis[y] = 1;
					cnt[y] ++;
					if (cnt[y] >= n) {
						flag = 1;
						return;
					}
				}
			}
		}
	}
}
int main () {
	scanf("%d", &t);
	while (t --) {
		flag = 0;
		memset(head, 0, sizeof(head));
		memset(ver, 0, sizeof(ver));
		memset(nex, 0, sizeof(nex));
		memset(edge, 0, sizeof(edge));
		memset(dis, 0x3f, sizeof(dis));
		memset(vis, 0, sizeof(vis));
		memset(cnt, 0, sizeof(cnt));
		scanf("%d%d", &n, &m);
		for (int i = 1; i <= m; i ++) {
			int a, b, w;
			scanf("%d%d%d", &a, &b, &w);
			if (w >= 0) {
				add(a, b, w);
				add(b, a, w);
			} else
				add(a, b, w);
		}
		spfa();
		if (flag)
			printf("YE5\n");
		else
			printf("N0\n");
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值