单源最短路径(最短路)

洛谷——P3371 【模板】单源最短路径(spfa)

题目描述

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

输入输出格式

输入格式:

第一行包含三个整数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

样例说明:

代码:

#include<queue>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 10001
#define maxn 2147483647LL
using namespace std;
queue<int>q;
inline int read()
{
    int x=0,f=1;
    char ch=getchar();
    while(ch<‘0‘||ch>‘9‘)
    {
        if(ch==‘-‘) f=-1;
        ch=getchar();
    }
    while(ch>=‘0‘&&ch<=‘9‘)
    {
        x=x*10+ch-‘0‘;
        ch=getchar();
    }
    return x*f;
}
struct Edge
{
    int to,ds,next;
}edge[500005];
int n,m,s,tot,x,y,z,dis[N],head[N];//n 点的个数   m 连边的条数   s 起点   dis 储存最小边
bool vis[N];//标记一个点是否在队列中
void add(int from,int to,int dis)
{
    tot++;
    edge[tot].to=to;
    edge[tot].ds=dis;
    edge[tot].next=head[from];
    head[from]=tot;
}//邻接链表存边
void spfa(int s)
{
    for(int i=1;i<=n;i++) vis[i]=false,dis[i]=maxn;//初始化
    dis[s]=0,vis[s]=true;//加入第一个点(起点)
    q.push(s);//将起点入队
    while(!q.empty())//如果队列不为空,就接着执行操作,直到队列为空
    {
        int x=q.front();//从队列的头元素开始进行更新最短路
        q.pop();  //将队列头元素弹出
        for(int i=head[x];i;i=edge[i].next)//枚举与该点连接的边 i=head[x]当前所要更新的点在队列中的位置 i=edge[i].next与当前点相连的点
        {
            if(dis[x]+edge[i].ds<dis[edge[i].to])//如果能更新最小值
            {
                dis[edge[i].to]=dis[x]+edge[i].ds;//更新最小值
                if(!vis[edge[i].to])//将所能更新的没入队的元素入队
                {
                  vis[edge[i].to]=true;//标记为已入队
                  q.push(edge[i].to);//推入队中
                }
            }
         }
        vis[x]=false;//将该点标记为出队列
    }
}
int main()
{
    n=read(),m=read(),s=read();
    for(int i=1;i<=m;i++)
    {
        x=read(),y=read(),z=read();
        add(x,y,z);//用邻接链表储存
    }
    spfa(s);
    for(int i=1;i<=n;i++)
      printf("%d ",dis[i]);
    return 0;
 } 
时间: 2024-08-27 18:04:39

单源最短路径(最短路)的相关文章

带负权图的单源最短路径算法:Bellman-Ford算法

算法简介 前面介绍过图的单源最短路径算法Dijkstra算法,然而Dijkstra算法无法判断含负权边的图的最短路.如果遇到负权,在没有负权回路存在时(负权回路的含义是,回路的权值和为负.)即便有负权的边,也可以采用Bellman-Ford算法正确求出最短路径. Bellman-Ford算法能在更普遍的情况下(存在负权边)解决单源点最短路径问题.对于给定的带权(有向或无向)图G=(V,E),其源点为s,加权函数 w是 边集 E 的映射.对图G运行Bellman-Ford算法的结果是一个布尔值,表

POJ 1847 Tram 单源最短路径

题意:轨道网,有若干转换器,每个转换器都和其他若干转换器相连,转换器初始指向第一个与其相连的转换器.问要到达终点需要最少转换多少次? 思路:可以用dijkstra单源最短路来做,把轨道网看做有向图(因为1第一个指向2,2的第一个不一定指向1),当前转换器处始指向的那个转换器之间的路径权值为0,其他路径权值为1,求一次起点到终点的最短路,结果就是最少转换次数,注意可能没有路径,这时要输出-1 代码: /* poj 1847 264K 0MS */ #include<cstdio> #includ

单源最短路径Dijkstra、BellmanFord、SPFA【模板】

Dijkstra算法: 将所有点分为两个集合.如果源点s到u的最短路径已经确定,点u就属于集合Va,否则属于集合Vb. 1.将源点s到图中各点的直接距离当做初始值记录为s到各点的最短距离,不能到达的记为INF.S到S距离为0. 2.在集合Vb中的点中找一个点u,使得源点s到该点u路径长度最短,将u从Vb中除去,加到V1中.这时候求出了当前S到u的最短路径. 3.把新确定的点u更新s到集合Vb中每一个点v的距离,如果s到u的距离加上u到v的直接距离小于当前s到v的距离,则表示新找到的最短路径长度比

Til the Cows Come Home(poj 2387 Dijkstra算法(单源最短路径))

Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 32824   Accepted: 11098 Description Bessie is out in the field and wants to get back to the barn to get as much sleep as possible before Farmer John wakes her for the morning milking. Bessi

(转)图算法单源最短路径Dijkstra算法(邻接表/邻接矩阵+优先队列STL)

一.前言 最短路径算法,顾名思义就是求解某点到某点的最短的距离.消耗.费用等等,有各种各样的描述,在地图上看,可以说是图上一个地点到达另外一个地点的最短的距离.比方说,我们把地图上的每一个城市想象成一个点,从一个城市到另一个城市的花费是不一样的.现在我们要从上海去往北京,需要考虑的是找到一条路线,使得从上海到北京的花费最小.有人可能首先会想到,飞机直达啊,这当然是时间消耗最小的方法,但是考虑到费用的高昂,这条线路甚至还不如上海到北京的高铁可取.更有甚者,假设国家开通了从上海到西藏,再从西藏到兰州

Dijkstra单源最短路径

Dijkstra单源最短路径 给定一个带权有向图G=(V,E) ,其中每条边的权是一个非负实数.另外,还给定 V 中的一个顶点,称为源.现在我们要计算从源到所有其他各顶点的最短路径长度.这里的长度是指路上各边权之和.这个问题通常称为单源最短路径问题. 下面给出两个计算单源最短路径的模板. Dijkstra_简化版:时间复杂度O(n^2),不可处理重边图 //计算图的以s点为起点的单源最短路径 //图中节点从1到n编号 //运行dijkstrea之前,需要先把图中两点间的距离保存在dist[i][

有代价的单源最短路径

问题:有代价的单源最短路径,并要求存储路径.(求最短的路径,并使代价最小) 特点: * 存储路径:决定了难以用dijkstra,可以用flody,用path[i][j]表示 i 想走到 j 迈出的第一步.假设k是 i->j 的中间节点,更新时候用path[i][j] = path[i][k],具体做法见link.但是flody比较耗时(O(N^3)) * 有代价:如果想用flody的话,有要求代价最小,就需要将最短路相等的都记录下来.边一多代价更上去了.所以还是dfs比较方便. 例题: PAT

SPFA算法-单源最短路径算法

1.介绍: SPFA算法:单源最短路径算法,一种高效的最短路径算法! 2.思路 (1)初始化 1>源点路径为0  :d[s]=0 ,其中s为源点 2>初始化d[N]为无穷大,即d[i]表示,源点s到i为无穷大INF 3>p[N]初始化为源点s或-1,表示没有前驱 (2)队列+松弛 1>读取队头顶点u,并将队头顶点u出队(记得消除标记): 2>将与点u相连的所有点v进行松弛操作,如果能更新估计值(即令d[v]变小),那么就更新; 3>另外,如果点v没有在队列中,那么要将点

单源最短路径算法

目录 基本性质 Bellman Ford算法 spfa(Shortest Path Faster Algorithm) 算法 Dijkstra 算法 例题练习 主要参考算法导论 基本性质 使用min_w(s,v)表示源节点s到v的最短路径长度: w(u,v)表示节点u到v的权重: u.d表示源节点s到节点u的当前路径长度: 松弛操作 relax(u,v,w) { if(u.d + w < v.d) { v.d = u.d + w; } } 三角不等式 min_w(s,v) <= min_w(s