ybtoj 最短路径课堂过关 例题2luogu P3385SPFA(判负环)负环判断 & 模板负环

Posted SSL_ZZL

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ybtoj 最短路径课堂过关 例题2luogu P3385SPFA(判负环)负环判断 & 模板负环相关的知识,希望对你有一定的参考价值。

【例题2】负环判断 & 【P3385】【模板】负环


Link

ybtoj 【最短路径课堂过关】【例题2】负环判断
luogu【P3385】【模板】负环
题面//因为不知道侵不侵权,有账号的直接看转送门就可了


题目大意

给定一个 n 个点的有向图,请求出图中是否存在从顶点 1 出发能到达的负环。
负环的定义是:一条边权之和为负数的回路。


解题思路

有生之年系列,原来就是n打成了m

就是简单的SPFA判负环,统计步数,如果步数超过了点数,也就代表有负环(如果有负环那么SPFA就会一直跑下去)


Code

#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>

using namespace std;

struct DT{
	int to, s, next;
}a[61000];
queue<int>q;
int T, n, m, x, y, s, num, now;
int dis[41000], v[41000], step[41000], head[41000];

int SPFA() {
	memset(dis, 0x7f, sizeof(dis));
	memset(v, 0, sizeof(v));
	memset(step, 0, sizeof(step)); 
	
	q.push(1);
	v[1] = 1, dis[1] = 0;
	
	while(!q.empty()) {
		now = q.front();
	    q.pop();
		v[now] = 0;
		for (int i = head[now]; i; i = a[i].next) {
			if (dis[a[i].to] > dis[now] + a[i].s) {
				dis[a[i].to] = dis[now] + a[i].s;
				
				step[a[i].to] = step[now] + 1;  //更新步数
				if (step[a[i].to] >= n)  //步数超过,表明有负环(就是这里的 n 打成了 m TAT)
					return 1;
					
				if (!v[a[i].to]) {
					q.push(a[i].to);
					v[a[i].to] = 1;
				}
			}
		}
	}
	return 0;
}

int main() {
	scanf("%d", &T);
	while(T--) {
		scanf("%d %d", &n, &m);
		num = 0;
		memset(head, 0, sizeof(head));
		memset(a, 0, sizeof(a));
		for (int i = 1; i <= m; i++) {
			scanf("%d %d %d", &x, &y, &s);
			a[++num] = (DT){y, s, head[x]};
			head[x] = num;
			if (s >= 0) {
				a[++num] = (DT){x, s, head[y]};
				head[y] = num;
			}
		}
		if (SPFA()) printf("YES\\n");
			else printf("NO\\n");
	}
}

以上是关于ybtoj 最短路径课堂过关 例题2luogu P3385SPFA(判负环)负环判断 & 模板负环的主要内容,如果未能解决你的问题,请参考以下文章

ybtoj RMQ问题课堂过关例题4矩阵最值

ybtoj最短路Dijkstra堆例题1单源最短路径

ybtoj 倍增问题课堂过关例题1查找编号

ybtoj 倍增问题课堂过关LCA例题3树上距离

ybtoj线段树课堂过关例题1求区间和

ybtoj背包问题课堂过关DP例题3宝物筛选