洛谷 P3385 【模板】负环

22 阅读1分钟

P3385 【模板】负环

这道题目就是spfa判断负权回路的板子题,其中我个人认为有两个值得注意的点:

1.注意审题,题目中根据w的值来判断两点之间是单项关系还是双向关系。

2.每一轮记得初始化cnt和bool数组的st,idx,ne,e,w等数组不用初始化的原因是因为不更新idx每一轮会对上一轮数据直接覆盖,不更新idx则每一轮idx都会拓展新的空间存放数据,不会受之前数据影响,但是cnt和st数组不受idx这个指针影响,所以一定要更新。

因为是板子题,就直接贴代码了

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

typedef unsigned long long ull;

typedef pair <ll , ll> pii;

typedef priority_queue <ll ,vector<ll> ,greater<ll> > xiao;  
  
typedef priority_queue <ll ,vector<ll> ,less<ll> > da; 
  
const int N=1e5   + 10,M = 0x3f3f3f3f;
  
const ull P = 131;

int n,m;
  
int h[N],ne[N],e[N],w[N],idx;
  
int dist[N],cnt[N];
  
bool st[N];

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

int spfa()
  
{
	
  memset(dist , M , sizeof dist);
  
	dist[1] = 0;
	
	queue <int> q;
	q.push(1);
	
	while(q.size())
	{
		int t = q.front();
		q.pop();
		
		st[t] = 0;
		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 1;
				}
				if(!st[j])
				{
					st[j] = 1;
					q.push(j);
				}
			}
		}
	}
	
	return 0; 
}

void work()
{
	
  memset(st , 0 , sizeof st);
  
	memset(cnt , 0 , sizeof cnt);  //注意初始化
	memset(h , -1 , sizeof h);
	
	cin>>n>>m;
	
	for(int i = 1 ; i <= m ; i++)
	{
		int a,b,c;
		cin>>a>>b>>c;
		if(c < 0)
		{
			add(a , b , c);
		}else
		{
			add(a , b , c);
			add(b , a , c);
		}
	}
	
	int t = spfa();
	
	if(t)
	{
		cout<<"YES"<<"\n";
	}else
	{
		cout<<"NO"<<"\n";
	}
}

int main()
{
	std::ios::sync_with_stdio(false);
    std::cin.tie(0),cout.tie(0);

	int t;
	cin>>t;
	
	while(t--)
	{
		work();
	}	
}