其他分享
首页 > 其他分享> > CF 938D Buy a Ticket - 最短路

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 

题解:

最短路+超级源点

为什么在考场上想了那么久 ———— 《打脸》

这种描述很轻松就可以看出来这是一道略微不太正经的最短路,不正经在哪???

二倍边权这个怎么处理不用说了吧………………

问题就在于如何处理点权??每个点都跑一下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;

}

标签:Buy,int,短路,源点,938D,p1,Ticket,演唱会,dis
来源: https://www.cnblogs.com/littleseven777/p/11845627.html