Dijkstra迪杰斯特拉+堆优化
众所周知,朴素的迪杰斯特拉的时间复杂度为O(n^2),这在某些题目当中是会超时的。但如果在迪杰斯特拉中枚举每个最短边时加入堆优化,则迪杰斯特拉的效率则会大大提高。
朴素版迪杰斯特拉
void dijkstra(int x) //x为起点,使用迪杰斯特拉查找起点到其他任意点的最短路径
{
for(int i = 1; i <= n; i++) dis[i] = w[x][i]; //dis[i]数组存储从x到i的最短路(迪杰斯特拉跑完之前不一定是最终解)
//w[i][j]数组存储从i到j的路径长度(这里用的邻接矩阵存储,也可以换成前向星等)
b[x] = 1; //b[i]数组存储此点是否被访问过
dis[x] = 0;
for(int i = 1; i <= n - 1; i++)
{
minl = maxx;
k = 0;
for(int j = 1; j <= n; j++) //查找可以更新的点
if((!b[j]) && (dis[j] < minl))
{
minl = dis[j];
k = j;
}
if(k == 0) break; //这一句也可以换成if(k == y) break;表示已经更新完从x到y的最短路
b[k] = true; //更新k点,把k标记为已确定最短路径
for(int j = 1; j <= n; j++) //更新与k相连的每个未确定最短路径的顶点j
if(dis[k] + w[k][j] < dis[j])
dis[j] = dis[k] + w[k][j]; //可以加上pre[j] = k用来记录前驱节点
}
}
加入堆优化
笔者在oj上找到了几个较好的不同类型的模板,大家可以灵活选择记忆理解。
题目
题目描述
如题,给出一个有向图,请输出从某一点出发到所有点的最短路径长度。
输入输出格式
输入格式:
第一行包含三个整数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