938-D 题目大意
给定一张\(n\)个顶点\(m\)条边的无向图,边带权,且每个点\(i\)有点权\(a[i]\),记\(dist(i,j)\)为点\(i\)到点\(j\)所有的路径中经过的最小的边权和,请求出对于每个点\(i\)的:
\[\min_j^n(dist(i,j)+a[j]) \]Solution
题目涉及最短路,启发我们使用\(dijkstra\)求解,但对每个点求一遍最短路复杂度过高。
观察式子,除去求最短路的\(dist\)外,还需要附带一个点权\(a[j]\)。一个经典的做法是化点权为边权,我们建立一个虚拟源点,把所有节点\(i\)向这个虚拟源点连一条边,边权设为\(a[i]\),然后从这个虚拟源点跑一遍\(dijkstra\)即可求出所有答案。
时间复杂度:\(O(mlogm)\)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
int main(){
ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
int n,m;
cin>>n>>m;
vector<vector<pair<int,ll>>> e(n+1);
for(int i=0;i<m;i++){
int x,y;
ll w;
cin>>x>>y>>w;
e[x].push_back({y,2LL*w});
e[y].push_back({x,2LL*w});
}
for(int i=1;i<=n;i++){
ll w;
cin>>w;
e[0].push_back({i,w});
}
vector<ll> dist(n+1,1e18);
vector<int> vis(n+1);
priority_queue<pair<ll,int>,vector<pair<ll,int>>,greater<>> q;
q.push({0,0});
dist[0]=0;
while(!q.empty()){
auto [d,x]=q.top();
q.pop();
if(vis[x]) continue;
vis[x]=1;
for(auto [y,w]:e[x]){
if(d+w<dist[y]){
dist[y]=d+w;
q.push({dist[y],y});
}
}
}
for(int i=1;i<=n;i++){
cout<<dist[i]<<" ";
}
return 0;
}
标签:dist,int,短路,源点,CF,938,vector,push
From: https://www.cnblogs.com/fengxue-K/p/18184401