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();
}
}