题意
一国家由 n 个城市构成,城市之间有若干双向通路。一乐队在每个城市举办一场演出, 每次演出的票价不同。每个城市中的人,如果在自己城市看演出,只需要花票钱。否则还要加上往返路费。问对于每个城市来说,里面的人看到演出的最小票价是多少。
思路
暴力做法 floyd 加 枚举。妥妥的超时(点和边上限 1e5)。
添加一个源点,到其他点的距离等于那些点的点权。则问题转化成了求其他点到这个点的距离,同时巧妙地把点权转化为边权。这样就可以用dijkstra算法求解单源最短路。
链接
http://codeforces.com/contest/938/problem/D
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const LL maxn = 2e5 + 10;
struct edge{
LL to;
LL cost;
edge(){}
edge(LL to, LL cost): to(to), cost(cost){}
bool operator < (edge a) const{
if(cost != a.cost) return cost > a.cost;
return to < a.to;
}
};
LL n, m;
vector<edge> G[maxn];
LL dis[maxn];
bool vis[maxn];
void solve(){
memset(dis, -1, sizeof dis);
dis[0] = 0;
priority_queue<edge> qu;
qu.push(edge(0, 0));
while(!qu.empty()){
edge d = qu.top();
qu.pop();
if(d.cost != dis[d.to]) continue;
vis[d.to] = true;
for(LL i = 0; i < G[d.to].size(); i++){
edge t = G[d.to][i];
if(!vis[t.to] && (dis[t.to] == -1 || dis[t.to] > d.cost + t.cost)){
dis[t.to] = d.cost + t.cost;
qu.push(edge(t.to, dis[t.to]));
}
}
}
}
int main(){
scanf("%I64d %I64d", &n, &m);
for(LL i = 1; i <= m; i++){
LL a, b, c;
scanf("%I64d %I64d %I64d", &a, &b, &c);
c <<= 1;
G[a].push_back(edge(b, c));
G[b].push_back(edge(a, c));
}
for(LL i = 1; i <= n; i++){
LL x;
scanf("%I64d", &x);
G[i].push_back(edge(0, x));
G[0].push_back(edge(i, x));
}
solve();
for(LL i = 1; i <= n; i++){
printf("%I64d ", dis[i]);
}
puts("");
return 0;
}