洛谷 P4779【模板】单源最短路径(标准版)

     洛谷 P4779【模板】单源最短路径(标准版)

题目背景

2018 年 7 月 19 日,某位同学在 NOI Day 1 T1 归程 一题里非常熟练地使用了一个广为人知的算法求最短路。

然后呢?

10060 ;

 AgCu ;

最终,他因此没能与理想的大学达成契约。

小 F 衷心祝愿大家不再重蹈覆辙。

题目描述

给定一个 N 个点, M 条有向边的带非负权图,请你计算从 S 出发,到每个点的距离。

数据保证你能从 S 出发到任意点。

输入输出格式

输入格式:

第一行为三个正整数 N, M, S。 第二行起 M 行,每行三个非负整数 ui,vi,wi ,表示从 ui 到 vi 有一条权值为 wi 的边。

输出格式:

输出一行 N 个空格分隔的非负整数,表示 S 到每个点的距离。

输入输出样例

输入样例#1: 复制
4 6 1
1 2 2
2 3 2
2 4 1
1 3 5
3 4 3
1 4 4
输出样例#1: 复制
0 2 4 3

说明

样例解释请参考 数据随机的模板题

≤ ≤ 100000 ;

≤ ≤ 200000 ;

S = 1 ;

≤ ui,v≤ N ;

≤ wi​ ≤ 109,

≤ w≤ 109 。

本题数据可能会持续更新,但不会重测,望周知。

思路:spfa+优先队列优化  or  dijkstra+堆优化

 用P3371中的代码(再开上long long),可以过掉后两个点,但前几个点都会TLE

#include<iostream>
#include<cstring>
#include<cctype>
#include<cstdio>
#include<vector>
#include<queue>
#define M 100005
using namespace std;
int n, m, s, a, b, c;
struct Edge {
    int to, dis;
};
vector<Edge> G[M];
inline int read() {
    int X = 0, z = 0; char ch = 0;
    while(!isdigit(ch)) z = ch == '-' ? 1 : 0, ch = getchar();
    while(isdigit(ch)) X = (X<<1) + (X<<3) + (ch^48), ch = getchar();
    return z ? -X : X;
}
long long dis[M];
bool inqueue[M];
struct Node {
    int x;
};
bool operator < (const Node &x, const Node &y) {
    return dis[x.x] > dis[y.x];
}
priority_queue<Node> Q;
int cnt;
bool hasout[M];
inline bool SPFA(int S) {
    memset(dis, 0x3f, sizeof dis);
    memset(inqueue, 0, sizeof inqueue);
    Q.push((Node) {
        S
    });
    inqueue[S] = 1; dis[S] = 0;
    int u, v, cost;
    while(!Q.empty()) {
        u = Q.top().x; Q.pop();
        if(!hasout[u]) cnt++;
        if(cnt == n) return 1;
        hasout[u] = 1;
        inqueue[u] = false;
        for(int i = 0; i < G[u].size(); ++i) {
            v = G[u][i].to;
            cost = G[u][i].dis;
            if(dis[v] > dis[u] + cost) {
                dis[v] = dis[u] + cost;
                if(!inqueue[v]) {
                    inqueue[v] = true;
                    Q.push((Node) {
                        v
                    });
                }
            }
        }
    }
    return 1;
}
int main() {
    n = read(); m = read(); s = read();
    for(register int i = 1; i <= m; ++i) {
        a = read(), b = read(), c = read();
        G[a].push_back((Edge) {
            b, c
        });
    }
    SPFA(s);
    for(register int i = 1; i <= n; ++i)
        printf("%d ", dis[i]);
        return 0;
}
spfa+优先队列

 

posted @ 2018-08-02 21:08  落云小师妹  阅读(221)  评论(0编辑  收藏  举报