Wormholes POJ - 3259(SPFA判负环模板)

题意:虫洞是很奇特的,因为它是一个**单向**通道,可让你进入虫洞的前达到目的地!他的N(1≤N≤500)个农场被编号为1..N,之间有M(1≤M≤2500)条路径,W(1≤W≤200)个虫洞。FJ作为一个狂热的时间旅行的爱好者,他要做到以下几点:开始在一个区域,通过一些路径和虫洞旅行,他要回到最开时出发的那个区域出发前的时间。也许他就能遇到自己了:)。为了帮助FJ找出这是否是可以或不可以,他会为你提供F个农场的完整的图(1≤F≤5)。所有的路径所花时间都不大于10000秒,所有的虫洞都回到不大于10000秒之前。

AC代码:

#include <iostream>
#include <cstring>
#include <string>
#include <cstdio>
#include <queue>
#include <algorithm>
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=1e6+5;
int tot,dis[maxn],head[maxn],num[maxn],vis[maxn];
int n,m,w;
struct node {
	int v,w,nxt;
} e[maxn];
void add(int u,int v,int w) {
	e[tot].v=v;
	e[tot].w=w;
	e[tot].nxt=head[u];
	head[u]=tot++;
} 
bool spfa() {
	memset(vis,0,sizeof(vis));
	memset(num,0,sizeof(num));
	queue<int>q;
	dis[1]=0;
	for(int i=1;i<=n;i++)q.push(i),vis[i]=1;
	while(q.size()) {
		int u=q.front();
		q.pop();
		vis[u]=0;
		for(int i=head[u]; i!=-1; i=e[i].nxt) {
			int v=e[i].v;
			if(dis[v]>dis[u]+e[i].w) {
				dis[v]=dis[u]+e[i].w;
				num[v]=num[u]+1;
				if(num[v]>n)return true;
				if(!vis[v]) {
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
	return false;
}
main() {
	IOS;
	int t;
	cin>>t;
	while(t--) {
		cin>>n>>m>>w;
		tot=1;
		memset(head,-1,sizeof(head));
		for(int i=1; i<=n; i++)dis[i]=inf;
		for(int i=1; i<=m; i++) {
			int x,y,z;
			cin>>x>>y>>z;
			add(x,y,z);
			add(y,x,z);
		}
		for(int i=1; i<=w; i++) {
			int x,y,z;
			cin>>x>>y>>z;
			add(x,y,-z);
		}
		if(spfa())cout<<"YES"<<endl;
		else cout<<"NO"<<endl;
	}
}

猜你喜欢

转载自blog.csdn.net/Alanrookie/article/details/107914695
今日推荐