CF 938D Buy a Ticket
算法標籤: 最短路
、圖論
題目
題目描述
流行樂隊“Flayer”將在n個城市開演唱會 這n個城市的人都想去聽演唱會 每個城市的票價不同 於是這些人就想是否能去其他城市聽演唱會更便宜(去要路費的) 輸入格式: 第一行包含兩個整數n和m 接下來m行 每行三個數 u v k 表示u城市到v城市要k元 接下來n個數 表每個城市的票價
輸入格式
The first line contains two integers \(n\) and \(m\) \(( 2<=n<=2·10^{5} , 1<=m<=2·10^{5} )\).
Then \(m\) lines follow,$ i $-th contains three integers \(v_{i}\) , \(u_{i}\) , and \(w_{i}\) \(( 1<=v_{i},u_{i}<=n,v_{i}≠u_{i} , 1<=w_{i}<=10^{12} )\) denoting \(i\) -th train route. There are no multiple train routes connecting the same pair of cities, that is, for each \((v,u)\)neither extra$ (v,u)$ nor$ (u,v) $present in input.
The next line contains nn integers \(a_{1},a_{2},...\ a_{k} ( 1<=a_{i}<=10^{12} )\) — price to attend the concert in \(i\)-th city.
輸出格式
Print \(n\) integers. \(i\) -th of them must be equal to the minimum number of coins a person from city $ i$ has to spend to travel to some city $ j$ (or possibly stay in city $ i $), attend a concert there, and return to city \(i (if~~ j≠i )\).
輸入輸出樣例
輸入 #1
4 2
1 2 4
2 3 7
6 20 1 25
輸出 #1
6 14 1 25
輸入 #2
3 3
1 2 1
2 3 1
1 3 1
30 10 20
輸出 #2
12 10 12
題解:
最短路+超級源點
爲什麼在考場上想了那麼久 ———— 《打臉》
這種描述很輕鬆就可以看出來這是一道略微不太正經的最短路,不正經在哪???
- 開完演唱會還需要回到原來的城市——二倍邊權
- 在每個點開演唱會有一定的點權——\(Important\)
二倍邊權這個怎麼處理不用說了吧………………
問題就在於如何處理點權??每個點都跑一下Dij??
——顯然做不到
考慮超級源點,把所有點都與超級源點連接一條邊權爲該點點權的邊,對於超級源點跑最短路。(除了超級源點與每個點之間的邊以外的所有邊都要存二倍邊權)。
這樣跑完直接就是結果了。
AC代碼
#include <bits/stdc++.h>
#define setI(x) freopen(x".in", "r", stdin);
#define setO(x) freopen(x".out", "w", stdout);
#define setIO(x) setI(x) setO(x)
using namespace std;
typedef long long ll;
char *p1, *p2, buf[100000];
#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
int rd() {
int x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-') {
f = -1;
}
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48);
c = nc();
}
return x * f;
}
ll lrd() {
ll x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-') {
f = -1;
}
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48);
c = nc();
}
return x * f;
}
const int N = 2e5 + 10;
const int inf = 0x3f3f3f3f;
int tot, head[N], to[N << 2], nxt[N << 2];
ll val[N << 2];
int n, m;
ll num[N];
ll dis[N];
bool vis[N];
void add(int x, int y, ll z) {
to[ ++ tot] = y;
val[tot] = z;
nxt[tot] = head[x];
head[x] = tot;
}
priority_queue < pair<ll, int> > q;
void dijkstra(int s)
{
memset(dis, 0x3f, sizeof dis);
// memset(vis, 0, sizeof vis);
dis[s] = 0;
q.push(make_pair(0, s));
while (!q.empty())
{
if (vis[q.top().second])
{
q.pop();
continue ;
}
int x = q.top().second;
q.pop();
vis[x] = 1;
for (int i = head[x]; i; i = nxt[i])
{
if (dis[to[i]] > dis[x] + val[i])
{
dis[to[i]] = dis[x] + val[i];
q.push(make_pair(-dis[to[i]], to[i]));
}
}
}
}
int main() {
// setIO("movie");
// scanf("%d%d", &n, &m);
n = rd(), m =rd();
for (int i = 1; i <= m; i ++ ) {
int a = rd(), b = rd();
ll c = lrd();
add(a, b, c * 2);
add(b, a, c * 2);
}
for (int i = 1; i <= n; i ++ ) {
num[i] = lrd();
add(0, i, num[i]);
}
dijkstra(0);
for (int i = 1; i <= n; i ++ ) {
printf("%lld ", dis[i]);
}
return 0;
}