题意:
有n个点,m条普通的双向的路,w条单向的虫洞,问是否能从某个点出发走一些路再回来时回到过去。
即判断是否有负环。
为什么能用spfa入队次数来判断负环是否存在我还没有弄明白,有大神看到可以解释一下吗?
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
#include<cmath>
#include<vector>
#define N 50000//记得开大一点,做的时候开5000RE了好几遍
#define inf 0x3f3f3f
using namespace std;
struct node
{
int to,w,next;
} s[N];
int n;
int tot;
int vis[N];
int dis[N];
int head[N];
int num[N];
void add(int u,int v,int w)//记得这个函数存的是边的信息(编号为tot的边的指向以及权值),而不是点的信息,
{
s[tot].to = v;
s[tot].w = w;
s[tot].next = head[u];
head[u] = tot++;//边的个数
}
int spfa()
{
queue<int> q;
memset(num,0,sizeof(num));
memset(vis,0,sizeof(vis));
for(int i = 1; i <= n; i++)//这里初始化可以用memset
{
dis[i] = inf;
}
dis[1] = 0;
num[1] = 1;
vis[1] = 1;
q.push(1);
while(q.size())
{
int u = q.front();
q.pop();
vis[u] = 0;
for(int i = head[u]; i != -1; i = s[i].next)
{
int v = s[i].to;
if(dis[v] > dis[u] + s[i].w)
{
dis[v] = dis[u] + s[i].w;
if(vis[v] == 0)
{
num[v]++;
if(num[v] >= n)//如果入队次数大于点的个数则存在负环
return 1;
vis[v] = 1;
q.push(v);
}
}
}
}
return 0;
}
int main()
{
int t,x,y;
int u,v,w;
scanf("%d",&t);
while(t--)
{
tot = 1;//tot为0或1没差
memset(head,-1,sizeof(head));
scanf("%d %d %d",&n,&x,&y);
while(x--)
{
scanf("%d %d %d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
while(y--)
{
scanf("%d %d %d",&u,&v,&w);
add(u,v,w*(-1));
}
if(spfa())
printf("YES\n");
else
printf("NO\n");
}
return 0;
}