Dijkstra算法 --- 单源最短路
2015-12-13 22:10
387 查看
Dijkstra算法适用于边权值为正的情况,可用于计算正权图上的单元最短路。
其伪代码如下:
设d[v0] = 0, 其他d[i] = INF
循环n次{
在所有未标号的结点中,选取d值最小的结点x
给结点x加上永久标号
对于从x出发的所有边,执行松弛操作。
}
//松弛操作的伪代码如下:
RELAX(u,v,w)
if(u.d + w(u,v) < v.d){
v.d = w.d + w(u,v);
pre[v] = u;
}
Dijkstra算法代码:
View Code
其伪代码如下:
设d[v0] = 0, 其他d[i] = INF
循环n次{
在所有未标号的结点中,选取d值最小的结点x
给结点x加上永久标号
对于从x出发的所有边,执行松弛操作。
}
//松弛操作的伪代码如下:
RELAX(u,v,w)
if(u.d + w(u,v) < v.d){
v.d = w.d + w(u,v);
pre[v] = u;
}
Dijkstra算法代码:
/* 改进的Dijkstra算法 --- 以边为存储结构 */ #include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; const int maxn = 100; const int INF = 65535; /* 边结构 */ struct Edge{ int from, to, dist;//from,to,dist分别为边起点、终点和权值 Edge(int u, int v, int d) :from(u), to(v), dist(d){} }; /* 此节点为优先队列的元素 相当于(i,d[i])二元组 */ struct HeapNode{ int d, u; //u记录最短路径,u为起点 bool operator<(const HeapNode& rhs) const{ return d > rhs.d; //小的优先 } HeapNode(int a, int b) :d(a), u(b){} }; /* 定义最短路算法结构体 由于边是用vector存储,且自动编号,似乎只适用于有向图 */ struct Dij{ int n, m; vector<Edge> edges; //边集---保存边信息(自动编号为0~m-1) vector<int> G[maxn]; //按点记录边 G[i]表示以i为起点的集合 //G[i][j]表示以i为起点的集合中其中一条边的在edges中的序号 bool visit[maxn]; //是否已经是永久标号 int d[maxn]; //s到各点的距离 s是起点 ---> 记录最短路 int pre[maxn]; //记录路径,pre[i]表示以i为终点的边的编号 /* n为顶点数 */ void init(int n){ this->n = n; for (int i = 0; i < n; ++i){ G[i].clear(); //以i为起点的集合清空 }//for(i) edges.clear(); //清空边集 } void AddEdge(int from, int to, int dist){ edges.push_back(Edge(from, to, dist)); //加入边集 m = edges.size(); //m-1即为当前加入的边的序号 G[from].push_back(m - 1); //无向图 加上反向边 有向图可省去下面三行 edges.push_back(Edge(to, from, dist)); m = edges.size(); G[to].push_back(m - 1); } void dijkstra(int s){ priority_queue<HeapNode> Q; for (int i = 0; i < n; ++i){ d[i] = INF; }//for(i) d[s] = 0; memset(visit, 0, sizeof visit); Q.push(HeapNode(0,s)); //0,s分别为距离和起点 while (!Q.empty()){ HeapNode x = Q.top(); Q.pop(); //优先小地出栈,即先找到最小的d int u = x.u; //if (visit[u]) // continue; visit[u] = true; for (int i = 0; i < G[u].size(); ++i){ Edge& e = edges[G[u][i]]; //取得以u为起点的边e if (d[u] + e.dist < d[e.to]){ //经过点u和e到达e.to能更小 d[e.to] = d[u] + e.dist; //更新最小路径 pre[e.to] = G[u][i]; //记录路径 Q.push(HeapNode(d[e.to], e.to) ); } }//for(i) } } }; int main() { Dij dij; int n, m; //点和边的数目 scanf("%d%d", &n, &m); dij.init(n); int a, b, c; for (int i = 0; i < m; ++i){ scanf("%d%d%d", &a, &b, &c); dij.AddEdge(a, b, c); } dij.dijkstra(0); for (int i = 0; i < dij.n; ++i){ printf("%3d", dij.d[i]); } printf("\n"); //pre记录的是路径 int k = 8; while (k){ printf("%3d", k); k = dij.edges[dij.pre[k]].from; //取得前一个结点, } printf("%3d\n", k); return 0; } /* 测试数据 9 16 0 1 1 0 2 5 1 2 3 1 3 7 1 4 5 2 4 1 2 5 7 3 4 2 3 6 3 4 5 3 4 6 6 4 7 9 5 7 5 6 7 2 6 8 7 7 8 4 结果: 数组d 0 1 4 7 5 8 10 12 16 0~8路径反序: 8 7 6 3 4 2 1 0 */
View Code
相关文章推荐
- android中手机定位
- Git 提高命令的可读性
- 无插件Vim编程技巧
- C语言程序练习
- Dialog && PopupWindow
- [hdoj试题]Box of Bricks
- 第三个Sprint冲刺第七天
- 读《世界是数字的》④
- 【SpringMVC架构】SpringMVC入门实例,解析工作原理(二)
- 文章标题
- android 自定义ListView显示微信聊天好友列表
- XMPP系列 - 03 - Openfire服务器源码导入Eclipse
- HTML之禁止输入文本
- mac 报commond no found
- RHEL7 之 Linux进程管理
- java图形程序设计之图片显示
- 自定义枚举类
- 有漏洞无作为才可怕、可耻!
- 爬虫(heritrix框架)
- 【SpringMVC架构】SpringMVC介绍(一)