CF-938-D-最短路

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;
}
posted @ 2024-05-10 15:08  fengxue-K  阅读(20)  评论(0)    收藏  举报