单源最短距离 Single Source Shortest Path
单源最短距离_示例程序_图模型_用户指南_MaxCompute-阿里云 https://help.aliyun.com/document_detail/27907.html
单源最短距离
更新时间:2018-06-08 22:48:48
Dijkstra 算法是求解有向图中单源最短距离(Single Source Shortest Path,简称为 SSSP)的经典算法。
最短距离:对一个有权重的有向图 G=(V,E),从一个源点 s 到汇点 v 有很多路径,其中边权和最小的路径,称从 s 到 v 的最短距离。
- 初始化:源点 s 到 s 自身的距离(d[s]=0),其他点 u 到 s 的距离为无穷(d[u]=∞)。
- 迭代:若存在一条从 u 到 v 的边,那么从 s 到 v 的最短距离更新为:d[v]=min(d[v], d[u]+weight(u, v)),直到所有的点到 s 的距离不再发生变化时,迭代结束。
由算法基本原理可以看出,此算法非常适合使用 MaxCompute Graph 程序进行求解:每个点维护到源点的当前最短距离值,当这个值变化时,将新值加上边的权值发送消息通知其邻接点,下一轮迭代时,邻接点根据收到的消息更新其当前最短距离,当所有点当前最短距离不再变化时,迭代结束。
代码示例
import java.io.IOException;
import com.aliyun.odps.io.WritableRecord;
import com.aliyun.odps.graph.Combiner;
import com.aliyun.odps.graph.ComputeContext;
import com.aliyun.odps.graph.Edge;
import com.aliyun.odps.graph.GraphJob;
import com.aliyun.odps.graph.GraphLoader;
import com.aliyun.odps.graph.MutationContext;
import com.aliyun.odps.graph.Vertex;
import com.aliyun.odps.graph.WorkerContext;
import com.aliyun.odps.io.LongWritable;
import com.aliyun.odps.data.TableInfo;
public class SSSP {
public static final String START_VERTEX = "sssp.start.vertex.id";
public static class SSSPVertex extends
Vertex<LongWritable, LongWritable, LongWritable, LongWritable> {
private static long startVertexId = -1;
public SSSPVertex() {
this.setValue(new LongWritable(Long.MAX_VALUE));
}
public boolean isStartVertex(
ComputeContext<LongWritable, LongWritable, LongWritable, LongWritable> context) {
if (startVertexId == -1) {
String s = context.getConfiguration().get(START_VERTEX);
startVertexId = Long.parseLong(s);
}
return getId().get() == startVertexId;
}
@Override
public void compute(
ComputeContext<LongWritable, LongWritable, LongWritable, LongWritable> context,
Iterable<LongWritable> messages) throws IOException {
long minDist = isStartVertex(context) ? 0 : Integer.MAX_VALUE;
for (LongWritable msg : messages) {
if (msg.get() < minDist) {
minDist = msg.get();
}
}
if (minDist < this.getValue().get()) {
this.setValue(new LongWritable(minDist));
if (hasEdges()) {
for (Edge<LongWritable, LongWritable> e : this.getEdges()) {
context.sendMessage(e.getDestVertexId(), new LongWritable(minDist
+ e.getValue().get()));
}
}
} else {
voteToHalt();
}
}
@Override
public void cleanup(
WorkerContext<LongWritable, LongWritable, LongWritable, LongWritable> context)
throws IOException {
context.write(getId(), getValue());
}
}
public static class MinLongCombiner extends
Combiner<LongWritable, LongWritable> {
@Override
public void combine(LongWritable vertexId, LongWritable combinedMessage,
LongWritable messageToCombine) throws IOException {
if (combinedMessage.get() > messageToCombine.get()) {
combinedMessage.set(messageToCombine.get());
}
}
}
public static class SSSPVertexReader extends
GraphLoader<LongWritable, LongWritable, LongWritable, LongWritable> {
@Override
public void load(
LongWritable recordNum,
WritableRecord record,
MutationContext<LongWritable, LongWritable, LongWritable, LongWritable> context)
throws IOException {
SSSPVertex vertex = new SSSPVertex();
vertex.setId((LongWritable) record.get(0));
String[] edges = record.get(1).toString().split(",");
for (int i = 0; i < edges.length; i++) {
String[] ss = edges[i].split(":");
vertex.addEdge(new LongWritable(Long.parseLong(ss[0])),
new LongWritable(Long.parseLong(ss[1])));
}
context.addVertexRequest(vertex);
}
}
public static void main(String[] args) throws IOException {
if (args.length < 2) {
System.out.println("Usage: <startnode> <input> <output>");
System.exit(-1);
}
GraphJob job = new GraphJob();
job.setGraphLoaderClass(SSSPVertexReader.class);
job.setVertexClass(SSSPVertex.class);
job.setCombinerClass(MinLongCombiner.class);
job.set(START_VERTEX, args[0]);
job.addInput(TableInfo.builder().tableName(args[1]).build());
job.addOutput(TableInfo.builder().tableName(args[2]).build());
long startTime = System.currentTimeMillis();
job.run();
System.out.println("Job Finished in "
+ (System.currentTimeMillis() - startTime) / 1000.0 + " seconds");
}
}
- 第 19 行:定义 SSSPVertex ,其中:
- 点值表示该点到源点 startVertexId 的当前最短距离。
- compute() 方法使用迭代公式:d[v]=min(d[v], d[u]+weight(u, v)) 更新点值。
- cleanup() 方法把点及其到源点的最短距离写到结果表中。
- 第 58 行:当点值没发生变化时,调用 voteToHalt() 告诉框架该点进入 halt 状态,当所有点都进入 halt 状态时,计算结束。
- 第 70 行:定义 MinLongCombiner,对发送给同一个点的消息进行合并,优化性能,减少内存占用。
- 第 83 行:定义 SSSPVertexReader 类,加载图,将表中每一条记录解析为一个点,记录的第一列是点标识,第二列存储该点起始的所有的边集,内容如:2:2,3:1,4:4。
- 第 106 行:主程序(main 函数),定义 GraphJob,指定 Vertex/GraphLoader/Combiner 等的实现,指定输入输出表。
单源最短距离 Single Source Shortest Path的更多相关文章
- AOJ GRL_1_B: Shortest Path - Single Source Shortest Path (Negative Edges) (Bellman-Frod算法求负圈和单源最短路径)
题目链接: http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_B Single Source Shortest Path ...
- AOJ GRL_1_A: Single Source Shortest Path (Dijktra算法求单源最短路径,邻接表)
题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_A Single Source Shortest Path In ...
- JAVA之单源最短路径(Single Source Shortest Path,SSSP问题)dijkstra算法求解
题目简介:给定一个带权有向图,再给定图中一个顶点(源点),求该点到其他所有点的最短距离,称为单源最短路径问题. 如下图,求点1到其他各点的最短距离 准备工作:以下为该题所需要用到的数据 int N; ...
- 单源最短路径-迪杰斯特拉算法(Dijkstra's algorithm)
Dijkstra's algorithm 迪杰斯特拉算法是目前已知的解决单源最短路径问题的最快算法. 单源(single source)最短路径,就是从一个源点出发,考察它到任意顶点所经过的边的权重之 ...
- [ACM_图论] Domino Effect (POJ1135 Dijkstra算法 SSSP 单源最短路算法 中等 模板)
Description Did you know that you can use domino bones for other things besides playing Dominoes? Ta ...
- algorithm@ Shortest Path in Directed Acyclic Graph (O(|V|+|E|) time)
Given a Weighted Directed Acyclic Graph and a source vertex in the graph, find the shortest paths fr ...
- Dijkstra 单源最短路径算法
Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...
- 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)
一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...
- Bellman-Ford 单源最短路径算法
Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...
随机推荐
- 实验c语言不同类型的指针互用(不推荐只是学习用)
#include <stdio.h> int main(int argc, char *argv[]) { printf("Hello, world\n"); ]; i ...
- Java Web框架play framework的下载与环境变量配置
Web项目的开发有着众多的框架,近期刚刚接触了play. 对于一个Java开发者来说,play是一个不可多得的好框架.以下我简介下怎样下载play .以及play的环境变量配置方法. (1)登录pla ...
- python模块学习之warnings
warnings.warn(message, category=None, stacklevel=, source=None) 发出警告,或者忽略它或引发异常. category参数(如果给定)必须是 ...
- poj2431优先队列
A group of cows grabbed a truck and ventured on an expedition deep into the jungle. Being rather ...
- lua工具库penlight--07函数编程(一)
函数编程 序列 Lua 迭代器 (最简单的形式) 是一个函数,可以多次调用返回一个或多个值.for in语句理解迭代器和循环,直到该函数将返回nil. Lua有标准的序列迭代器 (ipairs和pai ...
- (转)LUA正则表达式不完全指南
转自剑侠论坛,并稍微修改个别文字. 好不容易闲下来,研究了一下正则表达式,然后越钻越深,经过跟大神们讨论学习后,就没有然后了.总之╮(╯▽╰)╭很有用的一个东西,至少对于用户输入的读取方面会比较方便, ...
- :(23, 7) in class Queen, multiple overloaded alternatives of constructor Queen define default arguments. class Queen private(val name:String,prop:Array[String],private[scala02] val age:Int = 18){
- Python中集合类型(set)学习小结
set 是一个无序的元素集合,支持并.交.差及对称差等数学运算, 但由于 set 不记录元素位置,因此不支持索引.分片等类序列的操作. 初始化 复制代码代码如下: s0 = set()d0 = {}s ...
- 多线程中wait和notify的理解与使用
1.对于wait()和notify()的理解 对于wait()和notify()的理解,还是要从jdk官方文档中开始,在Object类方法中有: void notify() Wakes up a s ...
- android webview处理h5打开本地文件浏览器的功能
这周遇到一个比较棘手的问题,需要在android上边集成h5页面,并且在h5页面上,需要用户能够上传android本地的照片,一开始我以为webview会自动处理掉的,因此没太留意,当真正集成时,才发 ...