CF-938-D-最短路

938-D 题目大意

给定一张n个顶点m条边的无向图,边带权,且每个点i有点权a[i],记dist(i,j)为点i到点j所有的路径中经过的最小的边权和,请求出对于每个点i的:

minjn(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;
}
posted @   fengxue-K  阅读(11)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
点击右上角即可分享
微信分享提示