P8802 [蓝桥杯 2022 国 B] 出差

题目描述

A 国有 N 个城市,编号为 1…N 小明是编号为 1 的城市中一家公司的员工,今天突然接到了上级通知需要去编号为 N 的城市出差。

由于疫情原因,很多直达的交通方式暂时关闭,小明无法乘坐飞机直接从城市 1 到达城市 N,需要通过其他城市进行陆路交通中转。小明通过交通信息网,查询到了 M 条城市之间仍然还开通的路线信息以及每一条路线需要花费的时间。

同样由于疫情原因,小明到达一个城市后需要隔离观察一段时间才能离开该城市前往其他城市。通过网络,小明也查询到了各个城市的隔离信息。(由于小明之前在城市 1,因此可以直接离开城市 1,不需要隔离)

由于上级要求,小明希望能够尽快赶到城市 N, 因此他求助于你,希望你能帮他规划一条路线,能够在最短时间内到达城市 N 。

输入格式

第 1 行:两个正整数 N,M 表示 A 国的城市数量, M 表示末关闭的路线数量。

第 2 行: N 个正整数,第 i 个整数 Ci​ 表示到达编号为 i 的城市后需要隔离的时间。

第 3…M+2 行: 每行 3 个正整数, u,v,c, 表示有一条城市 u 到城市 v 的双向路线仍然开通着,通过该路线的时间为 c。

输出格式

第 1 行:1 个正整数,表示小明从城市 1 出发到达城市 N 的最短时间。(到达城市 N,不需要计算城市 N 的隔离时间)

输入输出样例

输入 #1

4 4
5 7 3 4
1 2 4
1 3 5
2 4 3
3 4 5

输出 #1

13

自己比较喜欢的dijkstr的写法

#include <bits/stdc++.h>

using namespace std;

const int inf = INT_MAX;

int n, m;
int c[1010];
int u, v, w;

struct node {
	int v;
	int w;
};

vector<vector<node>> e(1010);//邻接表

void add(int u, int v, int w) {
	e[u].push_back({v, w});
}

typedef pair<int, int> pii;
priority_queue<pii, vector<pii>, greater<pii>> q;//堆优化
vector<int> dis(1010, inf);

void dij() {
	dis[1] = 0;
	q.push({dis[1], 1});//距离	节点

	while (!q.empty()) {
		int d = q.top().first;
		int u = q.top().second;

		q.pop();

		if (d > dis[u])	continue;

		for (size_t i = 0; i < e[u].size(); i++) {
			int v_node = e[u][i].v;
			int w_node = e[u][i].w;

			if (dis[v_node] > dis[u] + w_node + c[v_node]) {
				dis[v_node] = dis[u] + w_node + c[v_node];
				q.push({dis[v_node], v_node});
			}
		}

	}
}

int main() {
	cin >> n >> m;

	for (int i = 1; i <= n; i++) {
		cin >> c[i];//城市停留时间
	}

	for (int i = 1; i <= m; i++) {
		cin >> u >> v >> w;
		add(u, v, w);
		add(v, u, w);//无向图
	}

	dij();

	cout << dis[n] - c[n];//不算城市 N 的隔离时间

	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值