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

题目大意:

题目链接:https://www.luogu.org/problemnew/show/P4779
给定一个NN个点,MM条有向边的带非负权图,请你计算从SS出发,到每个点的距离。


思路:

dij+dij+堆优化的最短路模板题。
其实就是在SPFASPFA中改成优先队列即可。和SPFASPFA基本一样。
时间复杂度:O((n+m)log n)O((n+m)log\ n)


代码:

#include <cstdio>
#include <queue>
#include <cstring>
using namespace std;

const int N=100010;
const int M=200010;
int n,m,S,x,y,z,tot,dis[N],head[N];
bool vis[N];
priority_queue<pair<int,int> > q;

struct edge
{
    int next,to,dis;
}e[M];

void add(int from,int to,int dis)
{
    e[++tot].to=to;
    e[tot].dis=dis;
    e[tot].next=head[from];
    head[from]=tot;
}

void dij()
{
    q.push(make_pair(0,S));  //优先队列
    memset(dis,0x3f3f3f3f,sizeof(dis));
    dis[S]=0;
    while (q.size())
    {
        int u=q.top().second;  //取出点
        q.pop();
        if (vis[u]) continue;
        vis[u]=1;
        for (int i=head[u];~i;i=e[i].next)
        {
            int v=e[i].to;
            if (dis[v]>dis[u]+e[i].dis)
            {
                dis[v]=dis[u]+e[i].dis;
                q.push(make_pair(-dis[v],v));  //入堆 
            }
        }
    }
}

int main()
{
    memset(head,-1,sizeof(head));
    scanf("%d%d%d",&n,&m,&S);
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&x,&y,&z);
        add(x,y,z);
    }
    dij();
    for (int i=1;i<=n;i++)
        printf("%d ",dis[i]);
    return 0;
}
posted @ 2019-01-18 21:54  全OI最菜  阅读(105)  评论(0编辑  收藏  举报