CF 938D Buy a Ticket - 最短路

CF 938D Buy a Ticket

題目鏈接:洛谷 CF938D 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;

}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章