spfa 判断负环poj3259

题目链接:http://poj.org/problem?id=3259

Description

While exploring his many farms, Farmer John has discovered a number of amazing wormholes. A wormhole is very peculiar because it is a one-way path that delivers you to its destination at a time that is BEFORE you entered the wormhole! Each of FJ's farms comprises N (1 ≤ N ≤ 500) fields conveniently numbered 1..NM (1 ≤ M ≤ 2500) paths, and W (1 ≤ W ≤ 200) wormholes.

As FJ is an avid time-traveling fan, he wants to do the following: start at some field, travel through some paths and wormholes, and return to the starting field a time before his initial departure. Perhaps he will be able to meet himself :) .

To help FJ find out whether this is possible or not, he will supply you with complete maps to F (1 ≤ F ≤ 5) of his farms. No paths will take longer than 10,000 seconds to travel and no wormhole can bring FJ back in time by more than 10,000 seconds.

Input

Line 1: A single integer, FF farm descriptions follow. 
Line 1 of each farm: Three space-separated integers respectively: NM, and W 
Lines 2..M+1 of each farm: Three space-separated numbers (SET) that describe, respectively: a bidirectional path between S and E that requires T seconds to traverse. Two fields might be connected by more than one path. 
Lines M+2..M+W+1 of each farm: Three space-separated numbers (SET) that describe, respectively: A one way path from S to E that also moves the traveler back T seconds.

Output

Lines 1..F: For each farm, output "YES" if FJ can achieve his goal, otherwise output "NO" (do not include the quotes).

Sample Input

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

Sample Output

扫描二维码关注公众号,回复: 2292156 查看本文章
NO
YES

Hint

For farm 1, FJ cannot travel back in time. 
For farm 2, FJ could travel back in time by the cycle 1->2->3->1, arriving back at his starting location 1 second before he leaves. He could start from anywhere on the cycle to accomplish this.

题目大意:给出一个混合图(无向图+有向图),无向图事路,有向图是虫洞,虫洞可以回到过去;

如果能回到过去(经过虫洞后原点时间减少了)能则输出yes,否则输出no

大佬们有好多fang方法判断负环,但是我目前只会一种QAQ。。

spfa模板判断fu'h负环,

首先输入该地图,然后从一个点开始查找最短路,之后就是套用spfa模板了,有负环的存在返回1,无返回0;

对于模板,分为三个步骤

初始化:首先初始化数组shuaxin(用来记录最短路)为INF,biaoji(用于标记是否在队列)为0(不在),num(记录某一点进入队列的次数)为0;

起点入列:

循环判断:取出队首元素,取消标记(不在队列),利用邻接矩阵刷新最短距离,对于没有入列但可以入列de的的点,入列,标记,判断是否该点重复使用n次,ru'g如果重复使用,说明有fu'h负环,返回1;如果走完全程仍没有重复次数>n的,则代表代表没有负环。

#include<stdio.h>
#include<string.h>  
#include<math.h>  
  
//#include<map>   
//#include<set>
#include<deque>  
#include<queue>  
#include<stack>  
#include<bitset> 
#include<string>  
#include<iostream>  
#include<algorithm>  
using namespace std;  
  
#define ll long long  
#define INF 0x3f3f3f3f  
#define clean(a,b) memset(a,b,sizeof(a))// 水印 
#define mod 1000000


int shuzu[510][510];
int shuaxin[510],num[510];
bool biaoji[510];
int n,m,w;

int spfa(int x)
{
	clean(biaoji,0);
	clean(num,0);
	clean(shuaxin,INF);
	queue<int> que;
	while(que.size())
		que.pop();
	//初始化完成
	biaoji[x]=1;
	shuaxin[x]=0;
	num[x]=1;
	que.push(x);
	//起点入列 
	while(que.size())
	{
		int can=que.front();//以改点为起点判断 刷新 
		que.pop();
		biaoji[can]=0;
		for(int i=1;i<=n;++i)
		{
			if(shuaxin[can]+shuzu[can][i]<shuaxin[i])
			{
				shuaxin[i]=shuzu[can][i]+shuaxin[can];//刷新 
				if(biaoji[i]==0)//判断 改点是否在队列 
				{
					biaoji[i]=1;
					num[i]++;//重复++ 
					if(num[i]>n)
						return 1;//有负环 
					que.push(i);
				}
				
			}
		}
	}
	return 0;
	
}

int main()
{
	int t;
	cin>>t;
	while(t--)
	{
		clean(shuzu,INF);
		
		cin>>n>>m>>w;
		for(int i=0;i<m;++i)
		{
			int s,e,l;
			cin>>s>>e>>l;
			if(shuzu[s][e]>l)
			{
				shuzu[s][e]=l;
				shuzu[e][s]=l;
			}
		}
		for(int i=0;i<w;++i)
		{
			int s,e,l;
			cin>>s>>e>>l;
			shuzu[s][e]=-l;//虫洞 
		}
		if(spfa(1))
			cout<<"YES"<<endl;
		else
			cout<<"NO"<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/qq_40482358/article/details/81105478