算法与数据结构实验题 10.33 坐火车

实验任务

在某国,有 \(n\) 个城市,有 \(m\) 条铁路将这 \(n\) 座城市连通,第 \(i\) 条铁路连通城市 \(u_i\)\(v_i\) ,乘坐该条铁路的时间为\(t_i\)。在乘坐铁路之前需要购买车票,在城市 \(i\) 购买车票的排队时间为 \(t_i\) ,现在小明想知道从城市 \(1\) 到城市 \(n\) 最少需要多久时间。

数据输入

第一行给出两个整数 \(n\)\(m\) ,代表城市的个数和铁路的数量。

第二行给出 \(n\) 个整数,第 \(i\) 个数表示在城市 \(i\) 购买车票的排队时间。

接下来 \(m\) 行,每行给出三个整数,表示第条铁路连通城市 \(u_i\)\(v_i\) ,花费的时间为 \(t_i\)

数据范围:\(1<=n<=3e5, n<=m<=5e5, 0<=t_i<=1e8, 0<=a_i<=1e8\)

数据输出

输出一行,包含一个整数,表示从城市 \(1\) 到城市 \(n\) 的最小时间

输入示例

3 3
1 2 3
1 2 1
2 3 1
1 3 2

输出示例

3

代码

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll inf=1e18;

int n,m,x,y,z,a[500010];
ll dis[500010],ans;

int cnt,head[500010]; 
struct node {
	int v,t,next;				// next[i]表示与第i条边同起点的上一条边的储存位置
}edge[1000010];
void add(int f,int t,int v) {	// f=from, t=to, v=val
	edge[cnt].t=t;
	edge[cnt].v=v;
	edge[cnt].next=head[f];		// head[i]表示以i为起点的最后一条边的储存位置 
	head[f]=cnt++;
}


int main()
{
	scanf("%d%d",&n,&m);
	memset(head,-1,sizeof head);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int i=1;i<=m;i++) {
		scanf("%d%d%d",&x,&y,&z);
		add(x,y,z+a[x]);
		add(y,x,z+a[y]);
	}
	for(int i=2;i<=n;i++) dis[i]=inf;
	queue<int>que;
	que.push(1);
	while(!que.empty()) {
		int f=que.front(); que.pop();
		for(int i=head[f];i!=-1;i=edge[i].next) {
			int t=edge[i].t,v=edge[i].v;
			if(dis[t]>dis[f]+v) {
				dis[t]=dis[f]+v;
				if(t==n) ans=dis[t];
				else que.push(t);
			}
		}
	}
	printf("%lld",ans);
	return 0;
}

思路

一个无向图的最短路考查,使用简单的SPFA进行实现,其中关于存边,我将购买车票的费用加入到每一条边的权值中,注意方向不同,存的车票费用也不同
参见:OI Wiki - 最短路 - SPFA

二改:由于忽略了数据范围导致寄了,注意要把dis数组开成long long,代码已更新

三改:DS卡我vector存图,现已加入链式前向星

posted @ 2024-11-26 19:43  Severj  阅读(630)  评论(0)    收藏  举报