java找图最短路径_有效地找到大图中的最短路径

added:

这些评论让我很好奇pygraph的性能如何解决OP的顺序问题,所以我做了一个玩具程序来找出答案 . 这是问题的略小版本的输出:

$ python2.6 biggraph.py 4 6

biggraph generate 10000 nodes 00:00:00

biggraph generate 1000000 edges 00:00:00

biggraph add edges 00:00:05

biggraph Dijkstra 00:01:32

biggraph shortest_path done 00:04:15

step: 1915 2

step: 0 1

biggraph walk done 00:04:15

path: [9999, 1915, 0]

对于10k节点和1M边缘来说也不算太糟糕 . 重要的是要注意,由pygraph计算Dijkstra的方式产生了每个节点相对于一个目标(任意节点0,并且在图中没有特权位置)的所有生成树的字典 . 因此,花费3.75分钟计算的解决方案实际上得出了"what is the shortest path from all nodes to the target?"的答案 . 确实一旦 shortest_path 完成了,走的答案仅仅是字典查找,基本上没有时间 . 值得注意的是,在图表中添加预先计算的边缘在约1.5分钟时相当昂贵 . 这些时间在多次运行中是一致的 .

我仍然等待 biggraph 5 6 在一台闲置的计算机上(每台处理器的Athlon 64,4800 BogoMIPS,全部都是核心)已运行超过四分之一小时 . 至少内存使用稳定在约0.5GB . 结果如下:

biggraph generate 100000 nodes 00:00:00

biggraph generate 1000000 edges 00:00:00

biggraph add edges 00:00:07

biggraph Dijkstra 00:01:27

biggraph shortest_path done 00:23:44

step: 48437 4

step: 66200 3

step: 83824 2

step: 0 1

biggraph walk done 00:23:44

path: [99999, 48437, 66200, 83824, 0]

这是很长一段时间,但它也是一个繁重的计算(我真的希望我腌制结果) . 这是好奇的代码:

#!/usr/bin/python

import pygraph.classes.graph

import pygraph.algorithms

import pygraph.algorithms.minmax

import time

import random

import sys

if len(sys.argv) != 3:

print ('usage %s: node_exponent edge_exponent' % sys.argv[0])

sys.exit(1)

nnodes = 10**int(sys.argv[1])

nedges = 10**int(sys.argv[2])

start_time = time.clock()

def timestamp(s):

t = time.gmtime(time.clock() - start_time)

print 'biggraph', s.ljust(24), time.strftime('%H:%M:%S', t)

timestamp('generate %d nodes' % nnodes)

bg = pygraph.classes.graph.graph()

bg.add_nodes(xrange(nnodes))

timestamp('generate %d edges' % nedges)

edges = set()

while len(edges) < nedges:

left, right = random.randrange(nnodes), random.randrange(nnodes)

if left == right:

continue

elif left > right:

left, right = right, left

edges.add((left, right))

timestamp('add edges')

for edge in edges:

bg.add_edge(edge)

timestamp("Dijkstra")

target = 0

span, dist = pygraph.algorithms.minmax.shortest_path(bg, target)

timestamp('shortest_path done')

# the paths from any node to target is in dict span, let's

# pick any arbitrary node (the last one) and walk to the

# target from there, the associated distance will decrease

# monotonically

lastnode = nnodes - 1

path = []

while lastnode != target:

nextnode = span[lastnode]

print 'step:', nextnode, dist[lastnode]

assert nextnode in bg.neighbors(lastnode)

path.append(lastnode)

lastnode = nextnode

path.append(target)

timestamp('walk done')

print 'path:', path

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
汉密尔顿是指一个无向含有一条包含所有节点的路径,称为汉密尔顿路径;如果该路径还是一个回路,则称为汉密尔顿回路。最路径指的是汉密尔顿路径所有边的权值之和最小。 下面是Java汉密尔顿路径的实现: ```java import java.util.Arrays; public class Hamiltonian { private static int INF = 0x3f3f3f3f; // 无穷大 /** * 返回汉密尔顿路径 * @param graph 的邻接矩阵表示 * @return 返回汉密尔顿路径长度 */ public static int shortestPath(int[][] graph) { int n = graph.length; int[][] dp = new int[1 << n][n]; for (int[] row : dp) { Arrays.fill(row, INF); } dp[1][0] = 0; // 起点为0 for (int i = 1; i < 1 << n; i++) { for (int j = 0; j < n; j++) { if (((i >> j) & 1) == 1) { // 判断节点是否在集合 for (int k = 0; k < n; k++) { if (((i - (1 << j)) >> k & 1) == 1) { // 判断前一个状态是否包含k节点 dp[i][j] = Math.min(dp[i][j], dp[i - (1 << j)][k] + graph[k][j]); } } } } } int ans = INF; for (int i = 1; i < n; i++) { // 枚举终点 ans = Math.min(ans, dp[(1 << n) - 1][i] + graph[i][0]); } return ans; } public static void main(String[] args) { int[][] graph = { {0, 2, 6, 5}, {2, 0, 4, 4}, {6, 4, 0, 2}, {5, 4, 2, 0} }; int ans = shortestPath(graph); System.out.println(ans); } } ``` 以上代码使用动态规划的思想,dp[i][j]表示状态为i时,以j节点为结尾的最路径。状态转移方程为:dp[i][j] = min(dp[i][j], dp[i - (1 << j)][k] + graph[k][j]),其k表示i除j节点外的另一个节点。最终答案为dp[(1 << n) - 1][i] + graph[i][0],其i为终点,(1 << n) - 1表示所有节点都在路径的状态。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值