ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

acwing 904. 虫洞(spfa判断负环,单链表写法)

2022-03-19 15:34:19  阅读:176  来源: 互联网

标签:cnt dist idx 904 int memset 负环 spfa sizeof


目录

题目传送门

题目描述

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

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

农夫约翰的每个农场中包含 NN 片田地,MM 条路径(双向)以及 WW 个虫洞。

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

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

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

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

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

输入格式

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

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

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

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

输出格式

输出共 FF 行,每行输出一个结果。

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

数据范围

1≤F≤51≤F≤5
1≤N≤5001≤N≤500,
1≤M≤25001≤M≤2500,
1≤W≤2001≤W≤200,
1≤T≤100001≤T≤10000,
1≤S,E≤N1≤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判断负环

分析

代码

#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring> 
using namespace std;
const int N = 510, M = 5210; // 
int h[N], e[M], w[M], ne[M], idx = 0; 
int dist[N]; // dist[i]表示到1到i的最短路的距离 
int cnt[N]; // cnt[i]表示到i点最短路的边数 
bool st[N]; // 
int n;
void add(int a, int b, int c)
{
	e[idx] = b;
	w[idx] = c;
	ne[idx] = h[a];
	h[a] = idx++;
}

bool spfa()
{
	memset(dist, 0, sizeof dist);
	memset(cnt, 0, sizeof cnt);
	memset(st, 0, sizeof st);
	
	queue<int> q;
	for(int i = 1; i <= n; i++)
	{
		st[i] = true;
		q.push(i);
	}
	
	while(q.size())
	{
		int t = q.front();
		q.pop();
		
		st[t] = false; // t不在队列中了
		
		for(int i = h[t]; i != -1; i = ne[i])
		{
			int j = e[i];
			if(dist[j] > dist[t] + w[i])
			{
				dist[j] = dist[t] + w[i];
				cnt[j] = cnt[t] + 1;
				
				if(cnt[j] >= n) return true;
				
				if(!st[j])
				{
					q.push(j);
					st[j] = true;	
				}	
			}	
		} 
	}
	return false;
}


int T, m1, m2;


void init()
{
	memset(h, -1, sizeof h);
	memset(e, 0, sizeof e);
	memset(ne, 0, sizeof ne);
	memset(w, 0, sizeof w);
	idx = 0;
}

int main()
{
	memset(h, -1, sizeof h);
	
	
	scanf("%d", &T);
	while(T--)
	{
		// 一定这里初始化,或者调用init() 
		memset(h, -1, sizeof h);
		idx = 0;
		
		
		int s, t, w;
		scanf("%d%d%d", &n, &m1, &m2);
		while(m1 --)
		{
			scanf("%d%d%d", &s, &t, &w);
			add(s, t, w), add(t, s, w); // 无向图	
		}	
		while(m2 --)
		{
			scanf("%d%d%d", &s, &t, &w);
			add(s, t, -w); // 负边 
		}
		if(spfa()) puts("YES");
		else	   puts("NO"); 
	} 
	return 0;
}

时间复杂度

参考文章

标签:cnt,dist,idx,904,int,memset,负环,spfa,sizeof
来源: https://www.cnblogs.com/VanHa0101/p/16026658.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有