1. 程式人生 > 實用技巧 >vue從入門到精通指南

vue從入門到精通指南

雖然SPFA已死,但是SPFA還是很有用處的

具體實現與dijkstra 相似,但是是利用佇列優化,在廣度上進行求解(可處理負邊權),在每次鬆弛時,保證所有深度為n的路徑最短

應用

1.存在負邊權
2.每個點可以被多次經過
3.判斷負(正)環

code

#include<iostream>
#include<cstdio>
#include<math.h>
#include<cstring>
#include<vector>
#include<queue>
#include<algorithm>
#define ll long long

const ll maxn=3e3+10;
ll t,n,m,tot;
ll dis[maxn],vis[maxn],ru[maxn],head[maxn];
std::vector<std::pair<ll,ll> > e[maxn]; 

inline void cl()
{
	tot=0;
	memset(head,0,sizeof(head));
	for(int i=1;i<=n;i++) e[i].clear();
}

inline bool spfa(ll x)
{
	for(int i=1;i<=maxn;i++) dis[i]=0x7fffffff,vis[i]=0,ru[i]=0;
	std::queue<ll> q;
	
	dis[x]=0;
	vis[x]=1;
	
	q.push(x);
	
	while(q.size())
	{
		ll u=q.front();
		q.pop();
		
		vis[u]=0;
		
		for(int i=0;i<e[u].size();i++)
		{
			ll v=e[u][i].first;
			ll w=e[u][i].second;
			
			if(dis[v]>dis[u]+w)
			{
				dis[v]=dis[u]+w;
				
				if(!vis[v])
				{
					q.push(v);
					vis[v]=1;
					
					ru[v]++;
					
					if(ru[v]>=n)//當存在負環時,會不斷經過環上的路徑更新最小值,當一條路徑被走過了 n 次以上,那麼圖中必然存在負環
					{
						return 1;
					}
				}
			}
		}
	}
	
	return 0;
}

int main(void)
{
	scanf("%lld",&t);
	
	while(t--)
	{
		cl();
		
		scanf("%lld %lld",&n,&m);
		
		for(int i=1;i<=m;i++)
		{
			ll x,y,z;
			scanf("%lld %lld %lld",&x,&y,&z);
			
			if(z>=0) e[y].push_back(std::make_pair(x,z));
			e[x].push_back(std::make_pair(y,z));
		}
		ll flag=spfa(1);
		
		if(flag) printf("YES\n");
		else printf("NO\n"); 
	}
	return 0;
}