问题描述

给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证没有负环)。请你计算从1号点到其他点的最短路(顶点从1到n编号)。

输入格式

第一行两个整数n, m。

接下来的m行,每行有三个整数u, v, l,表示u到v有一条长度为l的边。

输出格式
共n-1行,第i行表示1号点到i+1号点的最短路。
样例输入
3 3
1 2 -1
2 3 -1
3 1 2
样例输出
-1
-2
数据规模与约定

对于10%的数据,n = 2,m = 2。

对于30%的数据,n <= 5,m <= 10。

对于100%的数据,1 <= n <= 20000,1 <= m <= 200000,-10000 <= l <= 10000,保证从任意顶点都能到达其他所有顶点。

 
 
一开始的时候规模少看了一个零( =  = !!)  
用了写起来比较简单的floyd算法自己变形了一下,以下错误代码:
#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
const int MAXN = ;
int floyd[MAXN][MAXN];
int main(){
int m, n;
memset(floyd, , sizeof(floyd));
cin >> m >> n;
for (int i = ; i <= m; i++){
int from, to, value;
cin >> from >> to >> value;
floyd[from][to] = value;
}
for (int j = ; j <= n; j++)
for (int k = ; k <= n; k++){
if (floyd[][k] + floyd[k][j] < floyd[][j])
floyd[][j] = floyd[][k] + floyd[k][j];
}
for (int m = ; m <= n; m++)
cout << floyd[][m] << endl;
return ;
}

上网查了一下发现SPFA算法,利用队列优化了一下。

SPFA(Shortest Path Faster Algorithm)(队列优化)算法是求单源最短路径的一种算法,它还有一个重要的功能是判负环(在差分约束系统中会得以体现),在Bellman-ford算法的基础上加上一个队列优化,减少了冗余的松弛操作,是一种高效的最短路算法。

算法大致思路:

  s表示源点

  利用dist[x]表示从源点s到x的最短距离

  用Q队列来保存需要处理的结点

  用inQueue[x]保存点x是否在队列中

  初始化:dist[]数组全部赋值为无穷大,比如INT_MAX(一定要足够大, 我一开始就是给小了所以有些数据错了)

  dist[s] = 0

开始算法:队列+松弛操作

  读取Q队首元素并出队(记得把inQueue[Q.top()]置为false)

  对与队首结点相连的所有点v进行松弛操作(如果源点通过队首结点再到结点v的距离比源点直接到v的距离要短,就更新dist[v],并且如果inQueue[v] == false 即V当前不在队列中,则v入队,当队列Q为空时,判断结束)

代码如下:

    #include<cstdio>
#include<iostream>
#include<cstring>
#include<queue>
using namespace std;
const int MAXN = ;
const int MAXL = ;
const int INF = INT_MAX;
int dist[MAXN]; //dist[x]表示从源点到x所需的最短距离,初始为INF
int head[MAXN];
int M; //边的索引
bool inQueue[MAXN];
queue<int> Q; //队列Q用来存放可松弛周围结点的结点
struct Edge{
int value;
int to;
int next;
}edge[MAXL]; //采用链式前向星存储边集 //构建边集合
void add(int from, int to, int value){
edge[M].to = to;
edge[M].next = head[from];
edge[M].value = value;
head[from] = M++;
} //SPFA算法
void SPFA(int start){
dist[start] = ; //源点到自己的距离为0
Q.push(start);
inQueue[start] = true;
while (!Q.empty()){
int temp = Q.front(); //取队头元素
Q.pop();
for (int j = head[temp]; j != -; j = edge[j].next){
int toNode = edge[j].to;
if (dist[toNode] > dist[temp] + edge[j].value){ //本题保证无负环,否则需要利用一个数组判断j是否入队超过n次
dist[toNode] = dist[temp] + edge[j].value;
if (!inQueue[toNode]){
Q.push(toNode);
inQueue[toNode] = true;
}
}
}
inQueue[temp] = false;
}
}
int main(){
memset(head, -, sizeof(head));
int n, m;
scanf("%d%d", &n, &m);
for (int i = ; i <= n; i++){ //初始化
dist[i] = INF;
inQueue[i] = false;
}
for (int p = ; p <= m; p++){
int from, to, value;
scanf("%d%d%d", &from, &to, &value); //用cin速度好像要慢一倍= =
add(from, to, value);
}
SPFA();
for (int x = ; x <= n; x++){
printf("%d\n", dist[x]);
}
return ;
}
 

蓝桥杯-算法训练--ALGO-5 最短路的更多相关文章

  1. 蓝桥杯 算法训练 最短路 [ 最短路 bellman ]

    传送门   算法训练 最短路   时间限制:1.0s   内存限制:256.0MB     锦囊1   锦囊2   锦囊3   问题描述 给定一个n个顶点,m条边的有向图(其中某些边权可能为负,但保证 ...

  2. Java实现 蓝桥杯 算法训练 猴子吃包子(暴力)

    试题 算法训练 猴子吃包子 问题描述 从前,有一只吃包子很厉害的猴子,它可以吃无数个包子,但是,它吃不同的包子速度也不同:肉包每秒钟吃x个:韭菜包每秒钟吃y个:没有馅的包子每秒钟吃z个:现在有x1个肉 ...

  3. Java实现蓝桥杯 算法训练 大等于n的最小完全平方数

    试题 算法训练 大等于n的最小完全平方数 资源限制 时间限制:1.0s 内存限制:256.0MB 问题描述 输出大等于n的最小的完全平方数. 若一个数能表示成某个自然数的平方的形式,则称这个数为完全平 ...

  4. 蓝桥杯算法训练 java算法 表达式求值

    问题描述 输入一个只包含加减乖除和括号的合法表达式,求表达式的值.其中除表示整除. 输入格式 输入一行,包含一个表达式. 输出格式 输出这个表达式的值. 样例输入 1-2+3*(4-5) 样例输出 - ...

  5. java实现 蓝桥杯 算法训练 Password Suspects

    问题描述 在年轻的时候,我们故事中的英雄--国王 Copa--他的私人数据并不是完全安全地隐蔽.对他来说是,这不可接受的.因此,他发明了一种密码,好记又难以破解.后来,他才知道这种密码是一个长度为奇数 ...

  6. 蓝桥杯 算法训练 Torry的困惑(基本型)(水题,筛法求素数)

    算法训练 Torry的困惑(基本型) 时间限制:1.0s   内存限制:512.0MB      问题描述 Torry从小喜爱数学.一天,老师告诉他,像2.3.5.7……这样的数叫做质数.Torry突 ...

  7. 蓝桥杯 算法训练 区间k大数查询(水题)

    算法训练 区间k大数查询 时间限制:1.0s   内存限制:256.0MB 问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. ...

  8. 蓝桥杯--算法训练 区间k大数查询

                                                                                 算法训练 区间k大数查询   时间限制:1.0 ...

  9. 蓝桥杯 算法训练 ALGO-116 最大的算式

    算法训练 最大的算式   时间限制:1.0s   内存限制:256.0MB 问题描述 题目很简单,给出N个数字,不改变它们的相对位置,在中间加入K个乘号和N-K-1个加号,(括号随便加)使最终结果尽量 ...

  10. 蓝桥杯算法训练 区间k大数查询

    算法训练 区间k大数查询   问题描述 给定一个序列,每次询问序列中第l个数到第r个数中第K大的数是哪个. 输入格式 第一行包含一个数n,表示序列长度. 第二行包含n个正整数,表示给定的序列. 第三个 ...

随机推荐

  1. Java随机数的使用

    在java中实现随机数的类有两种,分别是和java.util.Math 和 java.util.Random 第一种:java.lang.Math.random() Math.random()方法创建 ...

  2. AngularJS概念概述和第一个使用例子

    点击查看AngularJS系列目录 转载请注明出处:http://www.cnblogs.com/leosx/ 概念概述 本节使用一个简单的例子简要介绍了AngularJS的重要组成部分. 概念 描述 ...

  3. uva11538

    解题思路: 1. 计数问题, 有三种相对摆放方式: 水平, 竖直, 对角线. 根据加法原理即可, 并且没有交集. 水平和竖直是一样的, 只要n*m矩形旋转90度. 所以结果是: n*m*(m-1)+n ...

  4. HDU1024 DP的优化 最大M子段和问题

    Max Sum Plus Plus Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  5. 将网页封装成苹果APP的牛逼方法,无需发布到appstore,无需越狱即可安装

    很多小伙伴都在开发自己的app, 有的实现实现比较简单,就是一个h5页面,然后想要打包成app发布出去. 这个想法很单纯 打包生成个app这个是很简单的,网上一堆打包工具,分分钟可以完成 但是... ...

  6. 学习札记 ----wind7下如何安装SqlServer数据库

    1.控制面板 ---找到程序和功能选项 如下图所示: 2.打开程序和功能后进入如下图所示的界面,点击打开或关闭window功能. 3.启动window7自带的IIS功能.如下图所示: 4.如上动作准备 ...

  7. Java IO编程全解(一)——Java的I/O演进之路

    转载请注明出处:http://www.cnblogs.com/Joanna-Yan/p/7419117.html JDK1.4之前的早期版本,Java对I/O的支持并不完善,开发人员在开发高性能I/O ...

  8. MongoDB快速入门

    http://www.yiibai.com/mongodb/mongodb_quick_guide.html 创建数据库 MongoDB use DATABASE_NAME 用于创建数据库.该命令如果 ...

  9. CoreCLR源码探索(七) JIT的工作原理(入门篇)

    很多C#的初学者都会有这么一个疑问, .Net程序代码是如何被机器加载执行的? 最简单的解答是, C#会通过编译器(CodeDom, Roslyn)编译成IL代码, 然后CLR(.Net Framew ...

  10. git学习整理(1)git clone 理解

    1.git clone 的理解 git clone默认会把远程仓库整个给clone下来 ,只能clone远程库的master分支并在本地默认创建一个master分支 ,无法clone所有分支,若想要其 ...