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

这道水题水得有点吃力。。。


杨爷出的毒瘤数据。。。

首先是非负权图,就用dijkstra。

边比较稀疏,用堆优化。

再打模板的时候发现问题:

在去出堆顶元素的时候,可能会出现重复节点。

重复节点使用一个done数组进行标记,如果不给的话会跑得很慢。

然后图又可能不连通。。。数据的锅。

不连通的dist是\(2^{31} - 1\)。这个是锅。

代码:

#include<cstdio>
#include<cstring>
#include<queue>
const int maxn = 100005, maxm = 200005;
struct Edges
{
    int next, to, weight;
} e[maxm];
int head[maxn], tot;
int n, m, s;
int dist[maxn];
bool done[maxn];
struct Nodes
{
    int v, w;
    bool operator < (const Nodes &rhs) const
    {
        return w > rhs.w;
    }
};
void link(int u, int v, int w)
{
    e[++tot] = (Edges){head[u], v, w};
    head[u] = tot;
}
int read()
{
    int ans = 0, s = 1;
    char ch = getchar();
    while(ch > '9' || ch < '0')
    {
        if(ch == '-') s = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9')
    {
        ans = ans * 10 + ch - '0';
        ch = getchar();
    }
    return s * ans;
}
void dijkstra()
{
    memset(dist, 0x3f, sizeof(dist));
    std::priority_queue<Nodes> q;
    dist[s] = 0;
    q.push((Nodes){s, dist[s]});
    while(!q.empty())
    {
        Nodes x = q.top(); q.pop();
        int u = x.v, dis = x.w;
        if(done[u]) continue;
        done[u] = true;
        for(int i = head[u]; i; i = e[i].next)
        {
            int v = e[i].to;
            if(dis + e[i].weight < dist[v])
            {
                dist[v] = dis + e[i].weight;
                q.push((Nodes){v, dist[v]});
            }
        }
    }
}
int main()
{
    n = read(), m = read(), s = read();
    while(m--)
    {
        int u = read(), v = read(), w = read();
        link(u, v, w);
    }
    dijkstra();
    for(int i = 1; i <= n; i++)
    {
        printf("%d", dist[i]);
        if(i != n) printf(" ");
    }
    printf("\n");
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Garen-Wang/p/9362606.html
今日推荐