Bellman-ford算法(poj3259 Wormholes)

本文详细解析了Bellman-Ford算法,并通过poj3295问题来阐述其应用。该问题涉及农夫约翰在含有虫洞的农场间旅行,寻找能够回到起点的路径。题目要求计算在限定时间内能否通过路径和虫洞回到起点。输入包括农场数量、路径数量、虫洞数量以及具体路径和虫洞信息。输出是对每个农场是否能完成旅行的判断。
摘要由CSDN通过智能技术生成

Bellman-ford算法和详解

http://www.wutianqi.com/blog/1912.html

poj3295

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

 
输入
第1行:一个整数F表示接下来会有F个农场说明。
每个农场第一行:分别是三个空格隔开的整数:N,M和W
第2行到M+1行:三个空格分开的数字(S,E,T)描述,分别为:需要T秒走过S和E之间的双向路径。两个区域可能由一个以上的路径来连接。
第M +2到M+ W+1行:三个空格分开的数字(S,E,T)描述虫洞,描述单向路径,S到E且回溯T秒。
输出
F行,每行代表一个农场
每个农场单独的一行,” YES”表示能满足要求,”NO”表示不能满足要求。
NO
YES

#include <iostream>
using namespace std;

typedef struct Edge{
	int u;
	int v;
	int weight;
}Edge;
Edge edge[6000];
int dis[501] = {}; 
const int inf = 0x3f3f3f3f;

int N, M, W;//N, nodenum; M edgenum; W negtive edgenum

bool bellman() {
	for (int i = 0; i < 501; ++i)
		dis[i] = inf;
	dis[1] = 0;

	//N-1次松弛操作
	for (int i = 1; i <= N - 1; ++i) {
		//遍历所有的边,对dis进行更新
		for (int j = 1; j <= 2*M + W; ++j) {
			if (dis[edge[j].v] > dis[edge[j].u] + edge[j].weight) {
				dis[edge[j].v] = dis[edge[j].u] + edge[j].weight;

			}
		}

	}
	//如果v顶点的dis[v]值大于另一个顶点经边(u, v)得到的值{dis[u]+weight(u, v)}
	//违反了dis的定义,说明存在负圈
	for (int i = 1; i <= 2*M; ++i) {
		if (dis[edge[i].v] > dis[edge[i].u] + edge[i].weight)
			return true;
	}
	return false;
}
int main() {
	int F;
	cin >> F;
	while (F--) {
		
		cin >> N >> M >> W;
		int index = 1;
		int a, b, c;
		for (int i = 1; i <= M; ++i) {
			cin >> a >> b >> c;
			edge[index].u = a;
			edge[index].v = b;
			edge[index++].weight = c;
			edge[index].u = b;
			edge[index].v = a;
			edge[index++].weight = c;
		}
		for (int i = M + 1; i <= M + W; ++i) {
			cin >> a >> b >> c;
			edge[index].u = a;
			edge[index].v = b;
			edge[index++].weight = -c;
		}
		
		cout << (bellman() ? "YES\n" : "NO\n");
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值