首页 技术 正文
技术 2022年11月14日
0 收藏 323 点赞 4,339 浏览 2321 个字

问题描述

给定一个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 ;
}

 

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:9,105
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,582
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,429
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,200
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,836
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,919