poj 3259 Wormholes spfa算法

点击打开链接

Wormholes
Time Limit: 2000MS   Memory Limit: 65536K
Total Submissions: 25582   Accepted: 9186

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

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.

题目大意是给你一些虫洞和路径,通过虫洞可以回到过去,题目问你是否经过这些虫洞可以回到最初开始的地方,并且时间还要是before
bellman-ford或者SPFA都能做,就是求负回路,bellman-ford的判断方法就是全图松弛 n - 1 次,如果还能继续松弛,说明有负圈回路,否则就说明没有负圈回路,bellman-ford有一个优化就是松弛的过程中如果在一次松弛过程中任何点都没有改变最短路径,那么就可以提前结束全图的松弛操作得到结果

spaf是bellman算法的一个优化,每次松弛的不是全图的点,而是与最短距离有变化的点相连的那些点,题目用到一个队列,每个点如果最短路径更新了,就扔到队列里,然后从队列中拿出点来松弛与其相连的点,如果一个点入队列的次数达到n此,说明图中有负圈

注意两个点之间可能有多条路径,选择权值较小的那条边留下

#include
#include
#include
#include
using namespace std;

int map[501][501];
int dis[501];
int n, m, w;
int s, e, t;

bool spfa()
{
	bool flag[501] = {0};
	int count[501] = {0};
	queue q;
	q.push(s);
	dis[s] = 0;
	int curr;
	int i;
	while(!q.empty())
	{
		curr = q.front();
		q.pop();
		for(i = 1; i <= n; i++)
		{
			if(map[curr][i] < 100000)
			{
				if(dis[i] > map[curr][i] + dis[curr] )
				{
					dis[i] = map[curr][i] + dis[curr];
					if(flag[i] == 0)
						q.push(i);
					count[i] ++ ;
					flag[i] = 1;
					if(count[i] >= n)
						return 0;
				}
			}
		}
		flag[curr] = 0;
	}
	return 1;
}
int main()
{
	int f;
	scanf("%d", &f);
	while(f--)
	{
		
		memset(dis,63, sizeof(dis));
		memset(map, 127, sizeof(map));
		scanf("%d %d %d", &n, &m, &w);

		int i;
		for(i = 0; i < m; i++)
		{
			scanf("%d %d %d", &s, &e, &t);
			map[s][e] = map[s][e] > t? t : map[s][e];
			map[e][s] = map[e][s] > t? t : map[e][s];
		}
		for(i = 0; i < w; i++)
		{
			scanf("%d %d %d", &s, &e, &t);
			map[s][e] = -t;
		}
		if(spfa())
			printf("NO\n");
		else
			printf("YES\n");
	}
	return 0;
}


你可能感兴趣的:(模板,北京大学POJ,图论)