POJ_3259_Wormholes_最短路算法判环

今天去游泳怎么样呢?不知道没有健康证能不能去啊。


题意:

这个题和1860差不多,昨天做了好几个这样的题,农夫John有很多田,给你从a到b或者从b到a要多长时间,同时还有一些虫洞,虫洞可以单向从a到b,倒流一定时间。问这个在POJ如此之屌的农夫FJ能不能从一个起点出发,回到那个起点,并且回到过去。



Input

Line 1: A single integer, F. F farm descriptions follow.
Line 1 of each farm: Three space-separated integers respectively: N, M, and W
Lines 2.. M+1 of each farm: Three space-separated numbers ( S, E, T) 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 ( S, E, T) 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).

我一直不明白这个农夫这么吊为什么还老师让代码狗帮他解决问题。虽然途中存在单向边,不像1860,但是同时这个题也没要求起点固定,所以仍然是只要存在环(这次是负环)就可以,用bellman或者SPFA就可以了。


代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<cstring>
using namespace std;
#define mxn 1010
#define mxm 5500//一开始忘了虫洞造成的边的个数了,结果g++TLE,c++RE
#define inf 0x3f3f3f3f
int first[mxn],vv[mxm],ww[mxm],nxt[mxm],cnt;
void init(){
	memset(first,-1,sizeof(first));
	cnt=0;
}
void add(int u,int v,int w){
	nxt[cnt]=first[u];
	first[u]=cnt;
	vv[cnt]=v;
	ww[cnt++]=w;
}
int n,m,w;
int t[mxn],rec[mxn];
bool flag[mxn];
bool spfa(int source){
	memset(rec,0,sizeof(rec));
	memset(flag,0,sizeof(flag));
	memset(t,0x3f,sizeof(t));
	t[source]=0;
	rec[source]=1;
	queue<int> q;
	while(!q.empty())	q.pop();
	q.push(source);
	flag[source]=true;
	while(!q.empty()){
		int now=q.front();
		flag[now]=false;
		q.pop();
		for(int i=first[now];i!=-1;i=nxt[i]){
			int tem = t[now] + ww[i];
			if(tem<t[vv[i]]){
				++rec[vv[i]];
				if(rec[vv[i]]>=n)	return true;
				t[vv[i]]=tem;
				if(!flag[vv[i]]){
					flag[vv[i]]=true;
					q.push(vv[i]);
				}
			}
		}
	}
	return false;
}
int main(){
	int cs;
	scanf("%d",&cs);
	for(int CS=1;CS<=cs;++CS){
		init();
		scanf("%d%d%d",&n,&m,&w);
		for(int i=0;i<m;++i){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			add(u,v,w);
			add(v,u,w);
		}
		for(int i=0;i<w;++i){
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			add(u,v,-w);
		}
		bool ans=spfa(1);
		if(ans)	puts("YES");
		else	puts("NO");
	}
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值