洛谷P3371 单源最短路径(Dijkstra+堆优化)

来源:互联网 发布:网络暴力英文ppt 编辑:程序博客网 时间:2024/06/06 09:21

题目描述

如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。

输入输出格式

输入格式:
第一行包含三个整数N、M、S,分别表示点的个数、有向边的个数、出发点的编号。

接下来M行每行包含三个整数Fi、Gi、Wi,分别表示第i条有向边的出发点、目标点和长度。

输出格式:
一行,包含N个用空格分隔的整数,其中第i个整数表示从点S出发到点i的最短路径长度(若S=i则最短路径长度为0,若从点S无法到达点i,则最短路径长度为2147483647)

输入输出样例

输入样例#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

说明

时空限制: 1000ms,128M

数据规模:

对于20%的数据:N<=5,M<=15

对于40%的数据:N<=100,M<=10000

对于70%的数据:N<=1000,M<=100000

对于100%的数据:N<=10000,M<=500000

显然是道随便写个SPFA就能水掉的题,发两个Dijkstra + 堆优化的板子

【代码1】STL

#include <iostream>#include <cstdio>#include <algorithm>#define fs first#define sc secondusing namespace std;const int N = 1e4 + 5, M = 5e5 + 5;int dis[N], cnt = 1; bool vis[N];pair<int, int> h[M];int n, m, src;inline int get(){    char ch; int res = 0;    while ((ch = getchar()) < '0' || ch > '9');    res = ch - '0';    while ((ch = getchar()) >= '0' && ch <= '9')     res = (res << 3) + (res << 1) + ch - '0';    return res;}inline void put(int x){    if (x > 9) put(x / 10);    putchar(x % 10 + 48);    }struct Edge{    int to, cst; Edge *nxt;}a[M], *T = a, *lst[N];inline void addEdge(const int &z, const int &y, const int &x){    (++T)->nxt = lst[x]; lst[x] = T; T->to = y; T->cst = z;}inline void Dijkstra(const int &st){    for (int i = 1; i <= n; ++i) dis[i] = 2147483647;    h[0].fs = dis[st] = 0; h[0].sc = st; int x, y;    for (int i = 1; i <= n; ++i)    {        while (vis[h[0].sc] && cnt) pop_heap(h, h + cnt), --cnt;        if (!cnt) break;        x = h[0].sc, pop_heap(h, h + cnt), --cnt;        vis[x] = true;        for (Edge *e = lst[x]; e; e = e->nxt)         if (dis[y = e->to] > dis[x] + e->cst)         {             dis[y] = dis[x] + e->cst;             h[cnt].fs = -dis[y]; h[cnt++].sc = y;             push_heap(h, h + cnt);         }    }}int main(){    n = get(); m = get(); src = get();    while (m--) addEdge(get(), get(), get());    Dijkstra(src);     for (int i = 1; i <= n; ++i) put(dis[i]), putchar(' ');}

【代码2】手写堆

#include <iostream>#include <cstdio>#include <algorithm>using namespace std;const int N = 1e4 + 5, M = 5e5 + 5;int dis[N], n, m, src; bool vis[N];inline int get(){    char ch; int res = 0;    while ((ch = getchar()) < '0' || ch > '9');    res = ch - '0';    while ((ch = getchar()) >= '0' && ch <= '9')     res = (res << 3) + (res << 1) + ch - '0';    return res;}inline void put(int x){    if (x > 9) put(x / 10);    putchar(x % 10 + 48);   }struct Edge{    int to, cst; Edge *nxt;}a[M], *T = a, *lst[N];struct point{    int s, t;    inline bool operator < (const point &x)    {        return s < x.s;    }    point() {}    point(const int &S, const int &T):     s(S), t(T) {}};struct SmaRt{    point g[M];  int len;    inline void Pop()    {        g[1] = g[len--];        int now = 1, nxt = 2; point res = g[1];        while (nxt <= len)        {            if (nxt < len && g[nxt | 1] < g[nxt]) nxt |= 1;            if (g[nxt] < res)             g[now] = g[nxt], nxt = (now = nxt) << 1;            else break;        }        g[now] = res;    }    inline void Push(point res)    {        g[++len] = res;        int now = len, nxt = len >> 1;        while (nxt)        {            if (res < g[nxt])             g[now] = g[nxt], nxt = (now = nxt) >> 1;            else break;        }        g[now] = res;    }}Q;inline void addEdge(const int &x, const int &y, const int &z){    (++T)->nxt = lst[x]; lst[x] = T; T->to = y; T->cst = z;}inline void Dijkstra(const int &st){    for (int i = 1; i <= n; ++i) dis[i] = 2147483647;    dis[st] = 0; Q.Push(point(0, st)); int x, y;    for (int i = 1; i <= n; ++i)    {        while (Q.len && vis[Q.g[1].t]) Q.Pop();        if (!Q.len) break;        vis[x = Q.g[1].t] = true; Q.Pop();        for (Edge *e = lst[x]; e; e = e->nxt)         if (dis[y = e->to] > dis[x] + e->cst)          dis[y] = dis[x] + e->cst, Q.Push(point(dis[y], y));    }}int main(){    n = get(); m = get(); src = get(); int x, y, z;    while (m--)     {        x = get(); y = get(); z = get();        addEdge(x, y, z);    }    Dijkstra(src);     for (int i = 1; i <= n; ++i) put(dis[i]), putchar(' ');}