Dijkstra算法:伪代码

 //G为图,一般设为全局变量,数组d[u]为原点到达个点的额最短路径, s为起点
Dijkstra(G, d[u], s){
初始化;
for (循环n次){
u = 是d[u]最小的且还未访问的顶点的标号;
记u已经被访问;
for (从u出发能到达的所有顶点v){
if (v未被访问&&以u为终结点使s到顶点v的最短距离d[u]更优){
优化d[v];
}
}
}

邻接矩阵版Dijkstra

 //邻接矩阵模板
const int MAXV = ;
const int INF = ; int n, G[MAXV][MAXV]; //n 为顶点数,MAXV为最大顶点数
int d[MAXV]; //起点到达各点的最短路径长度
bool vis[MAXV] = { false }; //标记数组,标记顶点i是否已经被访问 void Dijkstra(int s){ //初始化
fill(d, d + MAXV, INF);
d[s] = ; //起点到达自身的距离为0
for (int i = ; i < n; i++){ //循环n次,每次从未访问的顶点中取出一点,然后更新他的理解点距离起点的距离
int u = -, MIN = INF;
for (int j = ; j < n; j++){ //找到未访问的顶点中d[]最小的
if (vis[j] == false && d[j] < MIN){
u = j;
MIN = d[j];
}
} //找不到小于INF的d[u], 说明剩下的顶点和起点不连通
if (u == -) return ;
vis[u] = true; //标记为已访问
for (int v = ; v < n; v++){
//如果v为访问&&u可到达v且经u的中转可以是v到s距离更短,更新d[v]
if (vis[v] == false && G[u][v] != INF && d[u] + G[u][v] < d[v]){
d[v] = d[u] + G[u][v];
}
} } }

邻接表版:

 const int MAXV = ;
const int INF = ;
int n; int d[MAXV];
bool vis[MAXV] = { false }; struct Node{
int v, dis; //v为边的目标顶点,dis为边权
}; vector<Node> Adj[MAXV]; //存储图的邻接表 void Dijktra(int s){
//初始化vis和d[s]
fill(d, d + MAXV, INF);
d[s] = ;
//循环n次每次找出还未访问的且距离起点最近的顶点,取出并访问,更新与它相邻的顶点到起点的距离
for (int i = ; i < n; i++){
int u = -, MIN = INF;
for (int j = ; j < n; j++){
if (vis[j] == false && d[j] < MIN){
u = j;
MIN = d[j];
}
} //如果找不到小于inf的d[u],说明剩下的顶点和起点s不连通
if (u == -) return ;
vis[u] = true;
for (int v = ; v < Adj[u].size(); v++){
int ver = Adj[u][v].v;
if (vis[ver] == false && d[u] + Adj[u][v].dis < d[ver]){
d[ver] = d[u] + Adj[u][v].dis;
}
} }
}

邻接表版 + 第二标尺(边权,点权,最短路径数)

 const int MAXV = ;
const int INF = ; int n, G[MAXV][MAXV]; //n 为顶点数,MAXV为最大顶点数
int d[MAXV]; //起点到达各点的最短路径长度
bool vis[MAXV] = { false }; //标记数组,标记顶点i是否已经被访问 int pre[MAXV]; //存储每个结点的最短路径上的前驱结点 int cost[MAXV][MAXV] = {}; //边权花费
int c[MAXV] = { };
int w[MAXV]; //每个顶点的物资
int weight[MAXV]; //从起点到当前顶点所收集的总物资
int num[MAXV]; //从起点到达每个顶点的路径数量 void Dijkstra(int s){ //初始化
fill(d, d + MAXV, INF);
d[s] = ; //起点到达自身的距离为0
for (int i = ; i < n; i++){ //循环n次,每次从未访问的顶点中取出一点,然后更新他的理解点距离起点的距离
int u = -, MIN = INF;
for (int j = ; j < n; j++){ //找到未访问的顶点中d[]最小的
if (vis[j] == false && d[j] < MIN){
u = j;
MIN = d[j];
}
} //找不到小于INF的d[u], 说明剩下的顶点和起点不连通
if (u == -) return;
vis[u] = true; //标记为已访问
for (int v = ; v < n; v++){
//如果v为访问&&u可到达v且经u的中转可以是v到s距离更短,更新d[v]
if (vis[v] == false && G[u][v] != INF){
if (d[u] + G[u][v] < d[v]){
d[v] = d[u] + G[u][v];
pre[v] = u; //将u设置成v的前驱结点
c[v] = c[u] + cost[u][v];
w[v] = w[u] + weight[v];
num[v] = num[u];
}
/*else if (d[u] + G[u][v] == d[v] && c[u] + cost[u][v] < c[v]){
c[v] = c[u] + cost[u][v];
}*/
/* else if (d[u] + G[u][v] == d[v] && w[u] + weight[v] > w[v]){
w[v] = w[u] + weight[v];
}*/
else if (d[u] + G[u][v] == d[v]){
num[v] += num[u];
}
}
} } }

Dijkstra + DFS

DIjkstra: 求出所有最短路径和每个顶点到起点的最短距离

 const int INF = ;
const int MAXV = ; bool vis[MAXV] = { false }; int G[MAXV][MAXV];
int V[MAXV][MAXV];//边权
int W[MAXV]; //点权
int num = ;//最短路径条数
int d[MAXV]; //d[u]数组
int n, m, s, des; //顶点数 vector<int> pre[MAXV]; //存储每个顶点在最短路径上的前驱结点
vector<int> tempPath; //临时路径
vector<int> path; //最优路径
int optValue = INF; //最优值 //求出所有最短路径和每个顶点到起点的最短距离
void Dijkstra(int s){ //初始化d[], d[s];
fill(d, d + MAXV, INF);
d[s] = ;
pre[s].push_back(s); for (int i = ; i < n; i++){
//找出还未访问且距离起点最近的顶点
int u = -, MIN = INF;
for (int j = ; j < n; j++){
if (vis[j] == false && d[j] < MIN){
u = j;
MIN = d[j];
}
} //如果没有这样的顶点说明剩下的顶点不与起点相连
if (u == -) return;
vis[u] = true; //遍历u的邻接点,更新的d[u]和pre[]
for (int v = ; v < n; v++){
if (vis[v] == false){
if (d[u] + G[u][v] < d[v]){
d[v] = d[u] + G[u][v];
pre[v].clear(); //将原来的前驱结点都删除
pre[v].push_back(u);
}
else if (d[u] + G[u][v] == d[v]){
pre[v].push_back(u);
}
}
}
}
}

DFS: 遍历每条最短路径,求出第二标尺下的最优路径

 //遍历每条最短路径,求出第二标尺下的最优路径
void dfs(int v){ //如果v是叶子结点,计算当前路径的第二标尺值,如果更优则更新
if (v == s){
tempPath.push_back(v); //如果边权最为第二标尺
int value = ;
for (int i = tempPath.size() - ; i > ; i--){
value += V[tempPath[i]][tempPath[i - ]];
} //如果更优,替换最优值
if (optValue > value){
optValue = value;
path = tempPath;
} ////如果点权位第二标尺
//int value2 = 0;
//for (int i = 0; i < tempPath.size(); i++){
// value2 += W[i];
//}
//if (optValue < value2){
// optValue = value2;
//} //如果是路径数量
num++; tempPath.pop_back();
}
else {
tempPath.push_back(v); for (int i = ; i < pre[v].size(); i++){
dfs(pre[v][i]);
} tempPath.pop_back(); //清除当前路径,方便下条路径的添加
} }

题型实战:

                  1003 Emergency (25分)

As an emergency rescue team leader of a city, you are given a special map of your country. The map shows several scattered cities connected by some roads. Amount of rescue teams in each city and the length of each road between any pair of cities are marked on the map. When there is an emergency call to you from some other city, your job is to lead your men to the place as quickly as possible, and at the mean time, call up as many hands on the way as possible.

Input Specification:

Each input file contains one test case. For each test case, the first line contains 4 positive integers: N (≤500) - the number of cities (and the cities are numbered from 0 to N−1), M - the number of roads, C​1​​ and C​2​​ - the cities that you are currently in and that you must save, respectively. The next line contains N integers, where the i-th integer is the number of rescue teams in the i-th city. Then M lines follow, each describes a road with three integers c​1​​, c​2​​ and L, which are the pair of cities connected by a road and the length of that road, respectively. It is guaranteed that there exists at least one path from C​1​​ to C​2​​.

Output Specification:

For each test case, print in one line two numbers: the number of different shortest paths between C​1​​ and C​2​​, and the maximum amount of rescue teams you can possibly gather. All the numbers in a line must be separated by exactly one space, and there is no extra space allowed at the end of a line.

Sample Input:

5 6 0 2
1 2 1 5 3
0 1 1
0 2 2
0 3 1
1 2 1
2 4 1
3 4 1

Sample Output:

2 4

题目大意要求:求给定起点和终点,求两点之间的最短路径的数量,如果存在多条最短路径,取路径上所有点的点权之和最大的那条路径,输出点权之和

代码:

 #include <stdio.h>
#include <algorithm>
#include <string.h>
using namespace std; const int maxv = ;
const int INF = ;
int G[maxv][maxv] = { INF };
int n, m, c1, c2; // n 为顶点数,m为边数,c1为起点,c2为终点
int d[maxv]; // 起点到各点的距离
int num[maxv] = { }; // 起点到达个点的最短路径条数
int weight[maxv]; // 每个点的点权
int w[maxv]; // 每个点的最距离起点所能积累的最大点权之和
bool vis[maxv] = { false }; // 是否被访问过 void Dijkstra(int s){
// 初始化d[], w[]数组
fill(d, d + maxv, INF);
d[s] = ;
memset(w, , sizeof(w));
w[s] = weight[s];
num[s] = ;
for (int i = ; i < n; i++){
int u = -, min = INF;
// 寻找一个最小的且未访问过的d[u]
for (int j = ; j < n; j++){
if (vis[j] == false && min > d[j]){
min = d[j];
u = j;
}
}
if (u == -) return;
vis[u] = true;
for (int v = ; v < n; v++){
if (G[u][v] != INF && vis[v] == false){
if (G[u][v] + d[u] < d[v]){
d[v] = G[u][v] + d[u];
num[v] = num[u];
w[v] = w[u] + weight[v];
}
else if (G[u][v] + d[u] == d[v]){
num[v] += num[u];
if (w[u] + weight[v] > w[v]){
w[v] = w[u] + weight[v];
}
}
}
}
}
} int main()
{
// freopen("in.txt", "r", stdin);
scanf("%d %d %d %d", &n, &m, &c1, &c2);
for (int i = ; i < n; i++){
scanf("%d", &weight[i]);
} int u, v, dis;
fill(G[], G[] + maxv * maxv, INF);
for (int i = ; i < m; i++){
scanf("%d %d %d", &u, &v, &dis);
G[u][v] = G[v][u] = dis;
} Dijkstra(c1); printf("%d %d", num[c2], w[c2]); // fclose(stdin);
return ;
}

图的最短路径算法Dijkstra算法模板的更多相关文章

  1. python数据结构与算法——图的最短路径(Dijkstra算法)

    # Dijkstra算法——通过边实现松弛 # 指定一个点到其他各顶点的路径——单源最短路径 # 初始化图参数 G = {1:{1:0, 2:1, 3:12}, 2:{2:0, 3:9, 4:3}, ...

  2. 最短路径之Dijkstra算法及实例分析

    Dijkstra算法迪科斯彻算法 Dijkstra算法描述为:假设用带权邻接矩阵来表示带权有向图.首先引进一个辅助向量D,它的每个分量D[i]表示当前所找到的从始点v到每个终点Vi的最短路径.它的初始 ...

  3. 单源最短路径(dijkstra算法)php实现

    做一个医学项目,当中在病例评分时会用到单源最短路径的算法.单源最短路径的dijkstra算法的思路例如以下: 如果存在一条从i到j的最短路径(Vi.....Vk,Vj),Vk是Vj前面的一顶点.那么( ...

  4. 最短路径算法-Dijkstra算法的应用之单词转换(词梯问题)(转)

    一,问题描述 在英文单词表中,有一些单词非常相似,它们可以通过只变换一个字符而得到另一个单词.比如:hive-->five:wine-->line:line-->nine:nine- ...

  5. 【算法设计与分析基础】25、单起点最短路径的dijkstra算法

    首先看看这换个数据图 邻接矩阵 dijkstra算法的寻找最短路径的核心就是对于这个节点的数据结构的设计 1.节点中保存有已经加入最短路径的集合中到当前节点的最短路径的节点 2.从起点经过或者不经过 ...

  6. 数据结构与算法--最短路径之Dijkstra算法

    数据结构与算法--最短路径之Dijkstra算法 加权图中,我们很可能关心这样一个问题:从一个顶点到另一个顶点成本最小的路径.比如从成都到北京,途中还有好多城市,如何规划路线,能使总路程最小:或者我们 ...

  7. 最短路径 | 深入浅出Dijkstra算法(一)

    参考网址: https://www.jianshu.com/p/8b3cdca55dc0 写在前面: 上次我们介绍了神奇的只有五行的 Floyd-Warshall 最短路算法,它可以方便的求得任意两点 ...

  8. 经典树与图论(最小生成树、哈夫曼树、最短路径问题---Dijkstra算法)

    参考网址: https://www.jianshu.com/p/cb5af6b5096d 算法导论--最小生成树 最小生成树:在连通网的所有生成树中,所有边的代价和最小的生成树,称为最小生成树. im ...

  9. (转)最短路算法--Dijkstra算法

    转自:http://blog.51cto.com/ahalei/1387799         上周我们介绍了神奇的只有五行的Floyd最短路算法,它可以方便的求得任意两点的最短路径,这称为“多源最短 ...

随机推荐

  1. matlab bitset的理解

    在阅读别人的matlab程序中,发现了这个bitset函数.于是查阅资料搞明白了大概意思,意思如下: B= bitset(A,pos,V) 将A以二进制来表示,并将第pos个位置, 设置为 V 的值, ...

  2. Android 基础知识 -- Intent

    Intent (意图) Android通信的桥梁,可以通过Intent启动Activity , Service , 发送指定广播到Receiver <1> 启动Activity : sta ...

  3. .Net Core的总结

    一.什么是.NET Core .NET Core是一个开源通用的开发框架,支持跨平台,即支持在Window,macOS,Linux等系统上的开发和部署,并且可以在硬件设备,云服务,和嵌入式/物联网方案 ...

  4. 封装 axios

    大家是否有印象,在开发项目中,我们往往会把axios给封装起来,写在一个js文件夹里,最后引入的也是js文件夹,而不是直接对axios进行操作,那为什么? 1. 如果一个组件需要请求数据,就要用到ax ...

  5. 蓝桥杯第十届C组试题C

    从0开始,从右到左给这些字符串的每一位字母起个名字. 比如:A(1位)A(0位) A(2位)A(1位)A(0位) AA = 27, 可以看成(26 * 1)+ A(1) 因为:字母每经过一个轮回,可就 ...

  6. 理解LDAP与LDAP注入

    0x01 LDAP简介 LDAP,轻量目录访问协议 |dn :一条记录的位置||dc :一条记录所属区域||ou :一条记录所属组织||cn/uid:一条记录的名字/ID| 此处我更喜欢把LDAP和 ...

  7. MySQL启动失败故障思路

    1.1 查看 日志 默认路径在数据路径下,以当前主机名加上.err命名 如主机名为tz,数据路径为/mnt/mysql_data目录下 日志文件为tz.err [root@tz mysql_data] ...

  8. xmind修改默认配置

    XMIND使用过程中,输入英文字符的时候,第1.2层级的英文字母总是默认大写,手动修改很繁琐.默认字体,想切换成其他类型,也是要手动一个个去修改. 网上找了下相关的问题,找到一些解决办法,整理到文档中 ...

  9. Mac配置环境变量时终端显示bash-3.2解决方案

    1.问题描述 (base) -bash-3.2$ vi ~/.bash_profile (base) -bash-3.2$ source ~/.bash_profile 2.解决方案 无授权转,侵权删 ...

  10. 有一个树形结构,实现一个方法getKeys(data,str),获取字符串str在data中的所有上级节点的名称

    有一个树形结构,实现一个方法getKeys(data,str);获取字符串str在data中的所有上级节点的名称,例如: getKeys(data,'str1') 返回 ‘key1' getKeys( ...