CSUOJ 1885 条条大路通罗马(最长路径)

Description

罗马很远。

从探险家马可所在的城市出发,还要经过很多城市、经过很久才能到达罗马。

探险家马可出发了。虽然他没有地图、不知道路,但是他知道,他正在走的路是罗马人建造的,罗马的建筑师为了方便人们前往罗马,使得你从任何一个城市出发,都不会再回到这座城市。

其实马可并没有错,条条大道通罗马,只要一直向前,他总会到的。但是,如果选错了道路,那么他将要花费非常多的时间。

现在把世界上的城市从1到N标号,马可所在的城市是1号,罗马在N号。已知所有城市之间的道路和需要花费的时间,求马可在最坏情况下,需要多久才能到达罗马。

Input

输入包含不超过5组数据。

对于每组数据,第一行两个正整数N,M(N<=100000,M<=400000),表示世界上共有N座城市,M条城市之间的单行道路。

接下来M行,每行三个正整数,u,v,w,(u,v,w<=100000)表示从城市u到城市v有一条需要花费w的时间的单行道。

每组数据之后会有一个空行。

输入以一行一个整数0结束。

Output

对于每组数据,输出一行一个整数,表示马可最坏情况下需要花费多少时间才能到达罗马。

Sample Input

4 4
1 2 1
1 3 2
2 4 4
3 4 2

3 4
1 2 1
1 2 3
1 2 2
2 3 4

0

Sample Output

5
7

解题思路:边上权值取反,然后建图跑SPFA。注意取值范围,不要爆int

代码如下:

#include <iostream>
#include <queue>
#include <cstring>

using std::queue;
using std::cin;
using std::cout;
using std::endl;

const int maxn=100005;
const int maxm=400005;
const long long inf=1e20;

int head[maxn];
typedef struct Edge {
	int to;
	int cost;
	int next;
} edge;
edge edges[maxm];
int cnt,inque[maxn];
long long dis[maxn];
int n,m;
void init()
{
	memset(head, -1, sizeof(head));
	memset(inque, 0, sizeof(inque));
	cnt = 0;
}

void add_edge(int from , int to, int cost)
{
	edges[cnt].to = to;
	edges[cnt].cost = cost;
	edges[cnt].next = head[from];
	head[from] = cnt++;
}

queue<int> que;
void spfa()
{
	while(que.size()) que.pop();
	for(int i = 1; i <= n; i++) dis[i] = inf;
	dis[1] = 0,inque[1] = 1;
	que.push(1);
	while(que.size()) {
		int u = que.front();
		que.pop();
		inque[u] = 0;
		for(int i = head[u]; i != -1; i = edges[i].next) {
			if(dis[edges[i].to] > dis[u] + edges[i].cost) {
				dis[edges[i].to] = dis[u] + edges[i].cost;
				if(!inque[edges[i].to]) {
					que.push(edges[i].to);
					inque[edges[i].to] = 1;
				}
			}
		}
	}
	return ;
}

int main(void)
{
	while(cin>>n && n) {
		cin>>m;
		init();
		int u,v,w;
		for(int i = 0; i < m; i++) {
			cin>>u>>v>>w;
			add_edge(u,v,-w);
		}
		spfa();
		cout<<-dis[n]<<endl;
		cout<<endl;
	}
	return 0;
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值