题目链接 Buy a Ticket
题意 给定一个无向图。对于每个$i$ $\in$ $[1, n]$, 求$min\left\{2d(i,j) + a_{j}\right\}$
建立超级源点$n+1$, 对于每一条无向边$(x, y, z)$,$x$向$y$连一条长度为$2z$的边,反之亦然。
对于每个$a_{i}$, 从$i$到$n+1$连一条长度为$a_{i}$的边,反之亦然。
然后跑一边最短路即可。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define MP make_pair #define fi first #define se second typedef long long LL; const int N = 2e5 + 10; int n, m; LL dis[N]; struct node{ int u; LL w; friend bool operator < (const node &a, const node &b){ return a.w > b.w; } }; vector <node> v[N]; void dij(int s, LL dis[], vector <node> v[]){ priority_queue <node> q; static bool vis[N]; rep(i, 1, n) dis[i] = 1e18, vis[i] = false; q.push({s, 0}); dis[s] = 0; while (!q.empty()){ int u = q.top().u; q.pop(); if (vis[u]) continue; vis[u] = 1; for (auto edge : v[u]) if (dis[u] + edge.w < dis[edge.u]){ dis[edge.u] = dis[u] + edge.w; q.push({edge.u, dis[edge.u]}); } } } int main(){ scanf("%d%d", &n, &m); rep(i, 1, m){ int x, y; LL z; scanf("%d%d%lld", &x, &y, &z); v[x].push_back({y, z * 2}); v[y].push_back({x, z * 2}); } rep(i, 1, n){ LL x; scanf("%lld", &x); v[n + 1].push_back({i, x}); v[i].push_back({n + 1, x}); } dij(n + 1, dis, v); rep(i, 1, n) printf("%lld ", dis[i]); return 0; }