第一行输入三个整数
—— 结点数、道路数和送餐次数。
接下来
行,第
行输入三个整数
,表示一条连接
与
的双向道路,其长度为
。
最后一行输入
个整数
,其中
表示第
次送餐的目的学校。
输出一个整数,代表完成全部订单最少需要骑行的总距离。
3 2 2 1 2 1 1 3 2 2 3
6
小红先从美食街骑到2号学校,再返回美食街,骑行距离为1+1=2
小红先从美食街骑到3号学校,再返回美食街,骑行距离为2+2=4
因此总共的骑行距离为2+4=6
import sys from collections import defaultdict from heapq import * h = defaultdict(list) n, m, q = map(int, input().split()) st = [0] * (n + 1) dist = [10**10] * (n + 1) for _ in range(m): a, b, w = map(int, input().split()) h[a].append([b, w]) h[b].append([a, w]) # 堆优化的迪杰斯特拉算法,时间复杂度O(mlogn) q = [] dist[1] = 0 heappush(q, [0, 1]) while q: d, a = q[0] heappop(q) if st[a]: continue st[a] = 1 for b, w in h[a]: if not st[b] and(dist[b] > dist[a] + w): dist[b] = dist[a] + w heappush(q, [dist[a] + w, b]) res = 0 a = list(map(int, input().split())) for b in a: res += dist[b] * 2 print(res)
核心思想是堆优化的Dijkstra算法,基本上是模板题,但是要熟练的写出来还是有点难度。注意无向图的节点插入是双向的,另外边的数组要开大一点。
#include
using namespace std;
typedef pair PII;
typedef long long int ll;
const int N = 2e5+10;
int n; // 点的数量
int h[N], w[N], e[N], ne[N], idx; // 邻接表存储所有边
int dist[N]; // 存储所有点到1号点的距离
bool st[N]; // 存储每个点的最短距离是否已确定
// 求1号点到n号点的最短距离,如果不存在,则返回-1
int dijkstra()
{
memset(dist, 0x3f, sizeof dist);
dist[1] = 0;
priority_queue, greater> heap;
heap.push({0, 1}); // first存储距离,second存储节点编号
while (heap.size())
{
auto t = heap.top();
heap.pop();
int ver = t.second, distance = t.first;
if (st[ver]) continue;
st[ver] = true;
for (int i = h[ver]; i != -1; i = ne[i])
{
int j = e[i];
if (dist[j] > distance + w[i])
{
dist[j] = distance + w[i];
heap.push({dist[j], j});
}
}
}
if (dist[n] == 0x3f3f3f3f) return -1;
return dist[n];
}
void add(int a, int b, int c)
{
e[idx] = b, ne[idx] = h[a], w[idx] = c; h[a] = idx ++ ;
}
int main() {
memset(h, -1, sizeof h);
int m, q;
cin >> n >> m >> q;
while(m--){
int a, b, c;
cin >> a >> b >> c;
add(a,b,c);
add(b,a,c);
}
dijkstra();
ll sum = 0;
int idx;
while(q--){
cin >> idx;
sum += dist[idx];
}
cout << sum * 2 << endl;
return 0;
}
// 64 位输出请用 printf("%lld")
import heapq
def dijkstra(n, adj, start):
dist = [float("inf")] * (n + 1) # 初始化距离数组,所有距离设为无穷大
dist[start] = 0 # 起点到自身的距离为0
heap = [(0, start)] # 最小堆,存储 (距离, 节点) 元组
while heap:
d, u = heapq.heappop(heap) # 弹出当前距离起点最近的节点
# if d > dist[u]:
# continue # 如果弹出的距离大于已知最短距离,跳过
for v, w in adj[u]: # 遍历当前节点的所有邻接节点
if dist[v] > dist[u] + w: # 如果通过当前节点到达邻接节点的距离更短
dist[v] = dist[u] + w # 更新最短距离
heapq.heappush(heap, (dist[v], v)) # 将新的距离和节点加入堆中
return dist
n, m, q = map(int, input().split()) # 读取节点数n,边数m,目标学校数q
adj = [[] for _ in range(n + 1)] # 初始化邻接表
for _ in range(m):
u, v, w = map(int, input().split()) # 读取每条边的信息
adj[u].append((v, w)) # 添加边 u -> v,权重为 w
adj[v].append((u, w)) # 添加边 v -> u,权重为 w(无向图)
targets = list(map(int, input().split())) # 读取目标学校列表
dist = dijkstra(n, adj, 1) # 计算从节点1到所有节点的最短路径
total = sum(2 * dist[t] for t in targets) # 计算所有目标学校的往返距离之和
print(total) # 输出总骑行距离
#include <functional>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
using PII = pair<int, int>;
using LL = long long;
int n = 0, m = 0, q = 0;
vector<int> dist;
vector<vector<PII>> adj;
const int INF = 0x3f3f3f3f;
priority_queue<PII, vector<PII>, greater<>> pq;
void solve() {
dist[1] = 0;
pq.push({0, 1});
while (!pq.empty()) {
auto [dx, x] = pq.top();
pq.pop();
if (dx > dist[x]) continue;
for (auto& [y, w] : adj[x]) {
int new_dist = dx + w;
if (new_dist < dist[y]) {
dist[y] = new_dist;
pq.push({new_dist, y});
}
}
}
}
int main() {
cin >> n >> m >> q;
dist.resize(n + 1, INF);
adj.resize(n + 1);
for (int i = 0; i < m; i ++) {
int u = 0, v = 0, w = 0;
cin >> u >> v >> w;
adj[u].push_back({v, w});
adj[v].push_back({u, w});
}
solve();
LL ans = 0;
for (int i = 0; i < q; i ++) {
int a = 0;
cin >> a;
ans += 2 * dist[a];
}
cout << ans << endl;
return 0;
}
// 64 位输出请用 printf("%lld")