【YBTOJ】【Luogu P3385】【模板】负环

链接:

洛谷

题目大意:

判负环。

正文:

如果一个点被访问 \(n\) 次就说明有负环。

代码:

const int N = 2e3 + 10, M = 6e3 + 10;

inline ll Read()
{
	ll x = 0, f = 1;
	char c = getchar();
	while (c != '-' && (c < '0' || c > '9')) c = getchar();
	if (c == '-') f = -f, c = getchar();
	while (c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0', c = getchar();
	return x * f;
}

struct edge
{
	int to, val, nxt;
}e[M];
int head[N], tot;
void add(int u, int v, int w)
{
	e[++tot] = (edge) {v, w, head[u]}, head[u] = tot; 
	return;
}

int t, n, m;
bool vis[N];
queue <int> q;
int dis[N], cnt[N];

bool SPFA()
{
	memset (dis, 127 / 3, sizeof dis);
	memset (cnt, 0, sizeof cnt);
	memset (vis, 0, sizeof vis);
	for (; !q.empty(); q.pop());
	dis[1] = 0;
	cnt[1] = vis[1] = 1;
	q.push(1);
	for (; !q.empty(); )
	{
		int u = q.front(); q.pop(); vis[u] = 0;
		for (int i = head[u], v; i; i = e[i].nxt)
			if (e[i].val + dis[u] < dis[v = e[i].to])
			{
				dis[v] = e[i].val + dis[u];
				if (vis[v]) continue;
				vis[v] = 1;
				cnt[v] ++;
				q.push(v);
				if (cnt[v] >= n) return 1;
			}
	}
	return 0;
}

int main()
{
	for (t = Read(); t--; )
	{
		memset (head, 0, sizeof head);
		tot = 0;
		n = Read(), m = Read();
		for (int i = 1; i <= m; i++)
		{
			int u = Read(), v = Read(), w = Read();
			add(u, v, w);
			if (w >= 0) add(v, u, w);
		}
		if (SPFA()) puts("YES");
		else puts("NO");
	}
	return 0;
}
posted @ 2021-05-19 20:42  Jayun  阅读(36)  评论(0编辑  收藏  举报