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

【例题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");
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值