P3385 【模板】负环 spfa判断负环

P3385 【模板】负环

题目描述

暴力枚举/SPFA/Bellman-ford/奇怪的贪心/超神搜索

寻找一个从顶点1所能到达的负环,负环定义为:一个边权之和为负的环。

输入输出格式

输入格式:

 

第一行一个正整数T表示数据组数,对于每组数据:

第一行两个正整数N M,表示图有N个顶点,M条边

接下来M行,每行三个整数a b w,表示a->b有一条权值为w的边(若w<0则为单向,否则双向)

 

输出格式:

 

共T行。对于每组数据,存在负环则输出一行"YE5"(不含引号),否则输出一行"N0"(不含引号)。

 

输入输出样例

输入样例#1: 复制

2
3 4
1 2 2
1 3 4
2 3 1
3 1 -3
3 3
1 2 3
2 3 4
3 1 -8

输出样例#1: 复制

N0
YE5

说明

 2000n≤2000

3000m≤3000

−10000≤w≤10000

10T≤10

建议复制输出格式中的字符串。 本题数据感谢@negiizhao的精心构造,请不要使用玄学算法 本题数据有更新

 

这个题的输出坑的一匹 输出是YE5 和N0

然后就是通过判断他出现的次数有没有大于n   出现次数大于n就表示有负环

 

#include
using namespace std;
#define INF 2147483647;
const int maxn=10005;
const int maxm=500005;
int n,m,s,cnt,x,y,z,c[60005];
int dis[20005],vis[20005],head[60005];
struct node
{
	int x,y,sum,next;
}e[60005];
void add(int x,int y,int sum)
{
	cnt++;
	e[cnt].x=x;
	e[cnt].y=y;
	e[cnt].sum=sum;
	e[cnt].next=head[x];
	head[x]=cnt;
}
int spfa()
{
	queueq;
	for(int i=1;i<=n;i++)
	dis[i]=INF;
	dis[1]=0;
	memset(vis,0,sizeof(vis));
	memset(c,0,sizeof(c)); 
	q.push(1);//入队 
	vis[1]=1;//初始化 
	while(!q.empty())
	{
		int u=q.front();
		q.pop();//出队 
		vis[u]=0;//出队标记 
		for(int i=head[u];i;i=e[i].next)//所有u能走的路 
		{
			int v=e[i].y;
			if(dis[v]>dis[u]+e[i].sum)
			{
				dis[v]=dis[u]+e[i].sum;//取最小的 
				c[v]++;//更新 
				if(c[v]>n) return 0;//出现超过n次表示就有负环 
				if(vis[v]==0)//如果这个点没在队列里就标记入队 
				{
					vis[v]=1;
					q.push(v);
				}
			}
		} 
	}
	return 1;
}
int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		cin>>n>>m;
		memset(head,0,sizeof(head));
		for(int i=1;i<=m;i++)
		{
			cin>>x>>y>>z;
			add(x,y,z);
			if(z>=0)
			add(y,x,z);
		}
		if(spfa()==0) cout<<"YE5"<

 

 

你可能感兴趣的:(最短路,模板)