单源最短距离_示例程序_图模型_用户指南_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的更多相关文章

  1. 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 ...

  2. 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 ...

  3. JAVA之单源最短路径(Single Source Shortest Path,SSSP问题)dijkstra算法求解

    题目简介:给定一个带权有向图,再给定图中一个顶点(源点),求该点到其他所有点的最短距离,称为单源最短路径问题. 如下图,求点1到其他各点的最短距离 准备工作:以下为该题所需要用到的数据 int N; ...

  4. 单源最短路径-迪杰斯特拉算法(Dijkstra's algorithm)

    Dijkstra's algorithm 迪杰斯特拉算法是目前已知的解决单源最短路径问题的最快算法. 单源(single source)最短路径,就是从一个源点出发,考察它到任意顶点所经过的边的权重之 ...

  5. [ACM_图论] Domino Effect (POJ1135 Dijkstra算法 SSSP 单源最短路算法 中等 模板)

    Description Did you know that you can use domino bones for other things besides playing Dominoes? Ta ...

  6. 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 ...

  7. Dijkstra 单源最短路径算法

    Dijkstra 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法,由计算机科学家 Edsger Dijkstra 于 1956 年 ...

  8. 单源最短路径算法:迪杰斯特拉 (Dijkstra) 算法(二)

    一.基于邻接表的Dijkstra算法 如前一篇文章所述,在 Dijkstra 的算法中,维护了两组,一组包含已经包含在最短路径树中的顶点列表,另一组包含尚未包含的顶点.使用邻接表表示,可以使用 BFS ...

  9. Bellman-Ford 单源最短路径算法

    Bellman-Ford 算法是一种用于计算带权有向图中单源最短路径(SSSP:Single-Source Shortest Path)的算法.该算法由 Richard Bellman 和 Leste ...

随机推荐

  1. php-fig组织psr标准

    psr规范 基本代码规范,本篇规范制定了代码基本元素的相关标准,以确保共享的PHP代码间具有较高程度的技术互通性. 关键词 “必须”(MUST). “一定不可.一定不能”(MUST NOT). “需要 ...

  2. nekohtml转换html时标签变大写的问题

    public static Document transferByNeko(InputStream stream, String charset) { if (stream == null) retu ...

  3. Atitit.h5 web webview性能提升解决方案-----fileStrore缓存离线存储+http方案

    Atitit.h5 web webview性能提升解决方案-----fileStrore缓存离线存储+http方案 1. 业务场景 android+webview h5 css背景图性能提升1 2. ...

  4. atitit.印度教与java宗教的特点与观念对比 attilax总结

    atitit.印度教与java宗教的特点与观念对比 attilax总结 1. Java就是一种宗教 1 2. Java的教义思想,社区理念,价值观念 2 2.1. 教学语言,类似与印度教的祭祀万能 2 ...

  5. Atitit. Class  元数据的反射操作 api apache  工具

    Atitit. Class  元数据的反射操作 api apache  工具 1 BeanUtils & PropertyUtils & MethodUtils类使用方法 - 短裤党  ...

  6. TextView中超链接拦截

    TextView中的超链接点击时,其实是通过Intent方式的,因此会调用Activity中的startActivity(Intent intent)方法,所以可在此方法中做些简单的拦截操作 例如拦截 ...

  7. ffmpeg 日志系统av_log()

    一般使用Error, Warning, Debug3个级别即可(见下面的颜色).AV_LOG_QUIET 核心函数只有一个:av_log().使用av_log()在控制台输出日志的效果如下图所示. a ...

  8. 【Python】IDLE清屏

    上网搜,没搜到可用的快捷键.但看到一个通过打印空内容来清屏的方法,smart ef clear(): for i in range(60): print

  9. ADO编程:error C2011: 'LockTypeEnum' : 'enum' type redefinition

     C++ Code  123   // Import the ADO type library #import "C:\\Program Files\\Common Files\\syste ...

  10. boost数据结构variant

    variant和any有些类似,是一种可变类型,是对C/C++中union概念的增强和扩展:    普通的union只能持有普通数据类型,而不能持有string.vector等复杂类型,而varian ...