904. 虫洞(spfa判断负环模板题)

发布时间:2024年01月23日

904. 虫洞 - AcWing题库

农夫约翰在巡视他的众多农场时,发现了很多令人惊叹的虫洞。

虫洞非常奇特,它可以看作是一条?单向?路径,通过它可以使你回到过去的某个时刻(相对于你进入虫洞之前)。

农夫约翰的每个农场中包含?N?片田地,M?条路径(双向)以及?W?个虫洞。

现在农夫约翰希望能够从农场中的某片田地出发,经过一些路径和虫洞回到过去,并在他的出发时刻之前赶到他的出发地。

他希望能够看到出发之前的自己。

请你判断一下约翰能否做到这一点。

下面我们将给你提供约翰拥有的农场数量?F,以及每个农场的完整信息。

已知走过任何一条路径所花费的时间都不超过 10000?秒,任何虫洞将他带回的时间都不会超过?10000 秒。

输入格式

第一行包含整数?F,表示约翰共有?F?个农场。

对于每个农场,第一行包含三个整数?N,M,W。

接下来?M?行,每行包含三个整数?S,E,T,表示田地?S 和?E?之间存在一条路径,经过这条路径所花的时间为?T。

再接下来?W?行,每行包含三个整数?S,E,T,表示存在一条从田地?S?走到田地?E?的虫洞,走过这条虫洞,可以回到?T?秒之前。

输出格式

输出共?F?行,每行输出一个结果。

如果约翰能够在出发时刻之前回到出发地,则输出?YES,否则输出?NO

数据范围

1≤F≤5
1≤N≤500
1≤M≤2500
1≤W≤200
1≤T≤10000
1≤S,E≤N

输入样例:
2
3 3 1
1 2 2
1 3 4
2 3 1
3 1 3
3 2 1
1 2 3
2 3 4
3 1 8
输出样例:
NO
YES

解析:?

通过 SPFA(Shortest Path Faster Algorithm)算法检测图中是否存在负权环。

算法思想如下:

1. 使用 SPFA 算法求解单源最短路径问题,计算从每个点出发到其他所有点的最短路径。

2. 在遍历边的过程中,如果某个点被松弛了 `n` 次(`n` 为节点数),说明存在负权环。

3. 如果存在负权环,则输出 "YES",否则输出 "NO"。

具体实现中,将图中的正权边按照正常的方式添加,而将负权边的权值取相反数,这样就可以转化为求解负权环的问题。如果存在负权环,说明图中存在一条路径,经过这个路径的权值和为负,即存在一组边,形成了一个负权环。

?

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<utility>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<math.h>
#include<map>
#include<sstream>
#include<deque>
#include<unordered_map>
using namespace std;
typedef long long LL;
const int N = 505, M = 5205;
int n, m1, m2;
int h[N], e[M], w[M], ne[M], idx;
int q[N], vis[N], cnt[N],d[N];

void add(int a, int b, int c) {
	e[idx] = b, w[idx] = c, ne[idx] = h[a], h[a] = idx++;
}

int spfa() {
	memset(d, 0x3f, sizeof d);
	memset(cnt, 0, sizeof cnt);
	memset(vis, 0, sizeof vis);
	int hh = 0, tt = 0;
	for (int i = 1; i <= n; i++) {
		q[tt++] = i;
		vis[i] = 1;
	}
	while (hh != tt) {
		int t = q[hh++];
		if (hh == N)hh = 0;
		vis[t] = 0;

		for (int i = h[t]; i != -1; i = ne[i]) {
			int j = e[i];
			if (d[j] > d[t] + w[i]) {
				d[j] = d[t] + w[i];
				cnt[j] = cnt[t] + 1;
				if (cnt[j] > n)return 1;
				if (!vis[j]) {
					q[tt++] = j;
					if (tt == N)tt = 0;
					vis[j] = 1;
				}
			}
		}
	}
	return 0;
}

int main() {
	int T;
	cin >> T;
	while (T--) {
		memset(h, -1, sizeof h);
		idx = 0;
		scanf("%d%d%d", &n, &m1, &m2);
		int a, b, c;
		while (m1--) {
			scanf("%d%d%d", &a, &b, &c);
			add(a, b, c), add(b, a, c);
		}
		while (m2--) {
			scanf("%d%d%d", &a, &b, &c);
			add(a, b, -c);
		}
		if (spfa())cout << "YES" << endl;
		else cout << "NO" << endl;
	}
	return 0;
}

文章来源:https://blog.csdn.net/Landing_on_Mars/article/details/135795520
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。