学园城有
第一行输入三个整数,分别表示结点数、道路数、送外卖次数。
接下来行,每行输入三个整数
表示结点
和
之间有一条长度为
的道路。
最后一行输入个整数表示每次送外卖的学校
。
输出一个整数表示答案。
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")