Buy A Ticket(图论)

Buy A Ticket

题目大意

每个点有一个点权,每个边有一个边权,求对于每个点u的(min(2*d(u,v)+val[v]))(v可以等于u)

solution

想到了之前的虚点,方便统计终点的权值,将所有点和虚点建边,边权不变,这样只需要求虚点到其他点的最短路即可,就将多源最短路问题转换成了单源最短路

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;
struct Edge {
    int v, next;
    long long w;
} edges[1000000];
int head[300000], tot, vis[250000], n, m, u ,v;
long long dis[250000], a[230000], w;
void add(int x, int y, long long w) { edges[++tot] = (Edge){y, head[x], w}, head[x] = tot; }
struct node {
    int id;
    long long w;
    bool operator<(node b) const  { return w > b.w; }
};
void dijkstra(int x) {
    priority_queue<node> queue;
    dis[x] = 0;
    queue.push((node){x, 0});
    while (!queue.empty()) {
        node newn = queue.top();
        queue.pop();
        if (vis[newn.id]) continue;
        vis[newn.id] = 1;
        for (int i = head[newn.id]; i; i = edges[i].next) {
            int v = edges[i].v;
            if (dis[v] > dis[newn.id] + edges[i].w) {
                dis[v] = dis[newn.id] + edges[i].w;
                queue.push((node){v, dis[v]});
            }
        }
    }
}
int main() {
    memset(dis, 0x3f, sizeof(dis));
    scanf("%d%d", &n, &m);
    for (int i = 0; i < m; i++) scanf("%d%d%lld", &u, &v, &w), add(u, v, 2 * w), add(v, u, 2 * w);
    for (int i = 1; i <= n; i++) scanf("%lld", &a[i]), add(0, i, a[i]);
    dijkstra(0);
    for (int i = 1; i <= n; i++) printf("%lld ", dis[i]);
    return 0;
}
原文地址:https://www.cnblogs.com/rui-4825/p/12981770.html