SPFA判负环
Posted wxl-ezio
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SPFA判负环相关的知识,希望对你有一定的参考价值。
原理很简单,SPFA可以多次入队,那么如果一个点入队的次数比点的总数还要多,或是起点入队两次,那么这个图肯定存在负环
- 例题
#include<iostream>
#include<cstring>
#include<cstdio>
#include<queue>
#include<algorithm>
using namespace std;
struct zzz{
int f,
t,
len,
nex;
}e[10001*4];
int head[2001],tot;
inline void add(int x,int y,int z)
{
e[++tot].f=x;
e[tot].t=y;
e[tot].len=z;
e[tot].nex=head[x];
head[x]=tot;
}
inline int read()
{
int k=0,f=1; char c=getchar();
for(;c>'9'||c<'0';c=getchar())
if(c=='-') f=-1;
for(;c<='9'&&c>='0';c=getchar())
k=(k<<3)+(k<<1)+c-48;
return k*f;
}
bool SPFA(int n)
{
queue <int> q; int flag[2001]={0};
int dis[2001]; memset(dis,2,sizeof(dis));
bool vis[2001]; memset(vis,0,sizeof(vis));
dis[1]=0; q.push(1); vis[1]=1;
while(!q.empty())
{
int k=q.front(); q.pop(); vis[k]=0;
for(int i=head[k];i;i=e[i].nex)
{
int to=e[i].t;
if(dis[to]>dis[k]+e[i].len)
{
dis[to]=dis[k]+e[i].len;
if(!vis[to])
{
flag[to]++;
if(flag[to]>n)
return 1;
q.push(to);
vis[to]=1;
}
}
}
}
return 0;
}
int main()
{
int t=read();
while(t--)
{
tot=0; memset(head,0,sizeof(head));
int n=read(),m=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read(),z=read();
if(z<0)
add(x,y,z);
else
add(x,y,z), add(y,x,z);
}
if(SPFA(n))
printf("YE5
");
else
printf("N0
");
}
return 0;
}
Luogu P2850 [USACO06DEC]虫洞Wormholes
#include<iostream>
#include<cstdio>
#include<queue>
#include<cstring>
using namespace std;
inline int read()
{
int k=0; char c=getchar();
for(;!isdigit(c);) c=getchar();
for(;isdigit(c);c=getchar())
k=(k<<3)+(k<<1)+c-48;
return k;
}
struct zzz{
int f,
t,
len,
nex;
}e[3000*2]; int head[501*2],tot;
inline void add(int x,int y,int z)
{
e[++tot].f=x;
e[tot].t=y;
e[tot].len=z;
e[tot].nex=head[x];
head[x]=tot;
}
int dis[501*2],sum[501*2]; bool vis[501*2],flag;
queue <int> q;
int main()
{
int t; t=read();
while(t--)
{
memset(head,0,sizeof(head)); tot=0,flag=0;
memset(sum,0,sizeof(sum));
int n,m,w; n=read(),m=read(),w=read();
for(int i=1;i<=m;i++)
{
int x,y,z; x=read(),y=read(),z=read();
add(x,y,z); add(y,x,z);
}
for(int i=1;i<=w;i++)
{
int x,y,z; x=read(),y=read(),z=read();
add(x,y,-z);
}
memset(dis,2,sizeof(dis));
q.push(1); dis[1]=0; vis[1]=1;
while(!q.empty())
{
int k=q.front(); q.pop(); vis[k]=0;
for(int i=head[k];i;i=e[i].nex)
{
if(dis[e[i].t]>dis[k]+e[i].len)
{
dis[e[i].t]=dis[k]+e[i].len;
if(!vis[e[i].t])
{
vis[e[i].t]=1;
q.push(e[i].t);
sum[e[i].t]++;
if(sum[e[i].t]>n)
{
flag=1; break;
}
}
}
}
if(flag)
break;
}
if(flag)
printf("YES
");
else
printf("NO
");
}
return 0;
}
以上是关于SPFA判负环的主要内容,如果未能解决你的问题,请参考以下文章