atc abc463E 思路分享(最短路)
https://atcoder.jp/contests/abc463/tasks/abc463_e
题意
给定一张带边权无向图,另外任意两点 \(i,j\) 之间有传送门,代价为 \(X_i+X_j+Y\),求 \(1\) 到其他点的最短路.
\(2\le n \le 2\times 10^5\),\(0 \le m \le 2\times 10^5\).
思路
完全图中 \(i,j\) 的边权能拆成只与 \(i\) 和 \(j\) 单独有关的两部分,可以引入虚拟点 \(s\),连 \(i\to s\) 权值为 \(X_i+Y\) 的边,以及 \(s\to j\) 权值为 \(X_j\) 的边,这样边的数量就压到了 \(2n\).
时间复杂度 \(\mathcal{O}((n+m)\log n)\).
代码
//author:kzssCCC
#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll INF = 9e18;
void solve(){
int n,m,Y;
cin >> n >> m >> Y;
vector<vector<pair<ll,int>>> adj(n+1);
for (int i=0;i<m;i++){
int u,v,w;
cin >> u >> v >> w;
adj[u].emplace_back(w,v);
adj[v].emplace_back(w,u);
}
vector<int> X(n+1);
for (int i=1;i<=n;i++){
cin >> X[i];
}
for (int i=1;i<=n;i++){
adj[i].emplace_back(Y+X[i],0);
adj[0].emplace_back(X[i],i);
}
vector<ll> dis(n+1,INF);
dis[1] = 0;
priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<>> pq;
pq.emplace(0,1);
while (!pq.empty()){
auto [d,u] = pq.top();
pq.pop();
if (d>dis[u]) continue;
for (auto& [w,v]:adj[u]){
if (d+w<dis[v]){
dis[v] = d+w;
pq.emplace(dis[v],v);
}
}
}
for (int i=2;i<=n;i++){
cout << dis[i] << ' ';
}
cout << '\n';
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
int t = 1;
// cin >> t;
while (t--) solve();
return 0;
}

浙公网安备 33010602011771号