Poj 3259 Wormholes Bellman-Ford

描述
在探索他的许多农场时,农夫约翰发现了许多惊人的虫洞。虫洞非常特殊,因为它是一条单向路径,可把您在进入虫洞之前的时间 将您送至目的地! FJ的每个农场均包含 N(1≤N≤500)个田地,编号为 1到 N,M(1≤M≤2500)条路径和 W(1≤W≤200)虫洞。由于 FJ是一位热衷时间旅行的爱好者,因此他希望做到以下几点:从某个田地开始,经过一些路径和虫洞,并在他初次离开之前的某个时间返回到开始田地。也许他将能够因此见到自己:)。为了帮助 FJ查明是否可行,他将向您提供其农场F(1≤F≤5)的完整地图。没有任何路径会花费超过10,000秒的时间,虫洞也不会使FJ的返回时间超过提前10,000秒。
.
输入
第1行:单个整数F,有 F个农场。
每个农场的第 1行:三个以空格分隔的整数,N,M和 W(N个田地,M条双向路,N条单向路)
每个农场的第2到 M + 1行:三个用空格分隔的数字(S,E,T),分别描述:S和 E之间的双向路径,路径用时 T秒。两个农场可能通过一条以上的路径连接。
每个农场的 M + 2到 M + W + 1行:分别描述三个以空格分隔的数字S,E,T, 从S到E的单向路径使旅行者退回 T秒。
.
输出
行1到F:对于每个农场,如果FJ可以实现其目标,则输出“YES”,否则输出“NO”(不包括引号)。
.
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

//选择原点的不同不影响负环的判断,如果有负环则一定会更新 n次以上,所以可以自己随便选一个原点 
#include<iostream>
#include<cstdio>
const int N = 5300;
const int oo = 25000001;
using namespace std; 
int f,n,m,w,en,dis[N>>1];
struct Edge{
	int to,from,w;
}edge[N];

void read(int &x){
	char ch,last=' ';
	while((ch=getchar())<'0'||ch>'9') last = ch;
	for(x=0;isdigit(ch);ch=getchar())
		x = x*10+ch-'0';
	if(last=='-') x = -x;
}

void add(int x,int y,int t){
	edge[++en].to = y;
	edge[en].from = x;
	edge[en].w = t;
}

bool bellman_ford(){
	for(int i=1;i<=n;i++){
		bool f = false;
		for(int j=1;j<=en;j++)
			if(dis[edge[j].to]>dis[edge[j].from]+edge[j].w){
				dis[edge[j].to]=dis[edge[j].from]+edge[j].w;
				f = true;
			}
		if(!f) return false;
	}
	return true;
}

int main(){
	read(f);
	while(f--){
		read(n);read(m);read(w);
	//	printf("%d %d %d\n\n",n,m,w);
		for(int i=0,x,y,t;i<m;i++){
			read(x);read(y);read(t);
			add(x,y,t);
			add(y,x,t);
		} 
		for(int i=0,x,y,t;i<w;i++){
			read(x);read(y);read(t);
			add(x,y,-t);
		}
		for(int i=1;i<=n;i++) dis[i] = oo;
		dis[1]=0;
	//	dis[n]=0;
		if(bellman_ford())printf("YES\n");
		else printf("NO\n");
		en=0;
	} 
	return 0;
} 

本题是明显的判断负环。
需要注意的问题是要看oo=0x7fffffff 会不会溢出,溢出就变成负的了…可以根据题目条件说每条路径不超过10000、最多2500条路径来把oo设成25000001;

新学到的东西

  • 重新构图前向星需要初始化en和head[ ];简单存图(如上文)只需要初始化en;
  • Bellman-Ford 判断负环的结果 与选取的原点无关:反正都要更新那么多次,oo也是数也可以比大小der

2019.10.23.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值