求助

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

_Anonymous_ @ 2023-02-26 19:32:21

堆优化+链式前向星dijkstra,不知为何WA第一个点

//

#include<iostream>
#include<iomanip>
#include<vector>
#include<queue>
#include<stack>
#include<stdio.h>
#include<cstring>
#include<string.h>
#include<cstdio>
#include<string>
#include<algorithm>
#include<utility>
#include<limits.h>
#include<map>
#include<set>
#include<cmath>
#define debug cout << "OK" << endl;
using namespace std;

//链式前向星-------------------
struct edge{
    long long to, w, nxt;
}e[500010];
int head[500010], tot;

void init()
{
    memset(head, -1, sizeof(head));
    tot = 0;
}

void add(int u, int v, long long w)
{
    e[tot].to = v, e[tot].nxt = head[u], e[tot].w = w;
    head[u] = tot++;
}
//链式前向星end-------------------

//dijkstra-------------------
long long dis[100001];

void pre()
{
    memset(dis, -1, sizeof(dis));
}
//dijkstra-------------------

//堆优化-------------------
int heap[100001], len = 0;//堆中存储点编号
int wz[100001];//wz[i]表示编号为i的点在heap中的下标

void up(int x)
{
    int u = x, v = x / 2;
    while(u != 1)
    {
        if(dis[heap[u]] < dis[heap[v]])
        {
            swap(wz[heap[u]], wz[heap[v]]);
            swap(heap[u], heap[v]);
        }
        else
        {
            break;
        }
        u = v, v = u / 2;
    }
}

void down(int x)
{
    int u = x, v = x * 2;
    while(v <= len)
    {
        if(v + 1 <= len && dis[heap[v]] > dis[heap[v + 1]])
        {
            v++;
        }
        if(dis[heap[u]] > dis[heap[v]])
        {
            swap(wz[heap[u]], wz[heap[v]]);
            swap(heap[u], heap[v]);
        }
        else
        {
            break;
        }
        u = v, v = u * 2;
    }
}

void push(int x)
{
    heap[++len] = x;
    wz[x] = len;
    up(len);
}

int pop()
{
    int ans = heap[1];
    wz[heap[1]] = -1;
    heap[1] = heap[len--];
    down(1);
    return ans;
}
//堆优化end-------------------

int n, m, s;

int main()
{
    cin >> n >> m >> s;
    init();
    for(int i = 1; i <= m; i++)
    {
        int u, v;
        long long w;
        scanf("%d %d %lld", &u, &v, &w);
        add(u, v, w);
    }
    pre();
    memset(wz, -1, sizeof(wz));
    dis[s] = 0;
    push(s);
    while(len)//全部遍历过,堆内无点
    {
        // 暴力枚举
        // int mn, u = -1;
        // for(int j = 1; j <= n; j++)
        // {
        //     if(used[j] == 0 && dis[j] != -1 && (dis[j] < mn || u == -1))
        //     {
        //         mn = dis[j], u = j;
        //     }
        // }
        // if(u == -1)
        // {
        //     break;
        // }

        //取最近的点
        int u = pop();
        if(head[u] == -1)
        {
            continue;
        }
        for(edge j = e[head[u]];; j = e[j.nxt])
        {
            if(dis[j.to] > dis[u] + j.w || dis[j.to] == -1)
            {
                //松弛
                dis[j.to] = dis[u] + j.w;

                //进堆
                if(wz[j.to] == -1)
                {
                    push(j.to);
                }
                //维护
                else
                {
                    up(wz[j.to]);
                }
            }
            if(j.nxt == -1)
            {
                break;
            }
        }
    }
    for(int i = 1; i <= n; i++)
    {
        printf("%lld ", dis[i]);
    }
    cout << endl;
    return 0;
}

by _Anonymous_ @ 2023-02-26 19:33:23

悬一关


by Sun_Email @ 2023-02-26 20:10:40

没啥 看错了


by fengziyi @ 2023-02-26 20:38:55

不如 vector 存图


|