CF938D Buy a Ticket
CF938D Buy a Ticket
简单最短路练手题。
首先每个点都有自己的点权,根据经验,这肯定是要转边权的。
再看看题目,题目要求求每个人的去看的费用最小值,一般不难想出要跑 遍最短路,但是时间复杂度太高。
所以我们考虑建立一个虚拟原点,由于一开始的点是有点权的,所以我们把虚拟原点向所有的点连边,权值就是对应点的点权了。
这时候我们就可以只跑一边最短路, 数组就是答案了。
注意,由于要来回,所以边的值要双倍。
code:
#include<bits/stdc++.h>
using namespace std;
const int N =1e6+10;
#define int long long
struct node
{
int v;
int w;
};
vector<node> g[N<<1];
int dis[N];
struct State{
int u,d;
bool operator<(const State &s) const {
return d > s.d;
}
};
void dijkstra(int s){
priority_queue<State> que;
memset(dis,0x3f,sizeof(dis));
que.push(State{s,0}),dis[s] = 0;
while(!que.empty()){
int u = que.top().u,d = que.top().d;
que.pop();
if (d > dis[u]) continue;
for (int i = 0;i < g[u].size();++i){
int v = g[u][i].v,w = g[u][i].w;
if (dis[u] + w < dis[v]){
dis[v] = dis[u] + w;
que.push(State{v,dis[v]});
}
}
}
}
signed main()
{
int n,m;
cin>>n>>m;
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
g[u].push_back(node{v,w*2});
g[v].push_back(node{u,w*2});
}
for(int i=1;i<=n;i++)
{
int w;
cin>>w;
g[0].push_back(node{i,w});
}
dijkstra(0);
for(int i=1;i<=n;i++)
cout<<dis[i]<<" ";
return 0;
}