带权有向图 - 边上权值非负情形的单源最短路径问题

1. 问题描述:
给定一个带权有向图D与源点v, 求从v到D中其他顶点的最短路径。限定个边上的权值大于或等于0.

2. java实现:

package boke.graph.shortpath1;

import java.util.Stack;

/**
* 问题描述: 给定一个带权有向图D与源点v, 求从v到D中其他顶点的最短路径。限定个边上的权值大于或等于0.
*
* 带权有向图 - 边上权值非负情形的单源最短路径问题
*
* @since jdk1.5及其以上
* @author 毛正吉
* @version 1.0
* @date 2010.06.06
*
*/
public class Graph {
public static final float MAXNUM = Float.MAX_VALUE; // 表示无穷大

/**
* @param args
*/
public static void main(String[] args) {
int n = 5;
float[][] edge = { { 0, 10, MAXNUM, 30, 100 },
{ MAXNUM, 0, 50, MAXNUM, MAXNUM },
{ MAXNUM, MAXNUM, 0, MAXNUM, 10 },
{ MAXNUM, MAXNUM, 20, 0, 60 },
{ MAXNUM, MAXNUM, MAXNUM, MAXNUM, 0 } };
Graph g = new Graph(n, edge);

g.ShortestPath(5, 0);

float[] dist = g.getDist();
for (int i = 0; i < n; i++) {
System.out.print(dist[i] + " "); // 输出到给顶点的最短路径长度
}
System.out.println("");

// 读取从源点0到终点4的最短路径
int[] ph = g.getPath();
int len = ph.length;
System.out.println(len);
Stack sk = new Stack();
int idx = ph[4];
sk.push(4);
if (idx > 0) {
sk.push(idx);
}
while (idx >= 0 && ph[idx] != 0) {
idx = ph[idx];
if (idx > 0) {
sk.push(idx);
}
}
sk.push(0);

while (!sk.isEmpty()) {
Integer p = (Integer) sk.pop();
System.out.print(p + " "); // 输出源点0到终点4的最短路径
}
}

private int numVertices; // 图的最大定点个数
private float[][] edge; // 图的邻接矩阵
private float[] dist; // 存放从顶点0到其他各顶点的最短路径长度
private int[] path; // 存放在最短路径上该顶点的前一顶点的顶点号
private int[] S; // 已求得的在最短路径上的顶点的定点号

public Graph(int _numVertices, float[][] _edge) {
numVertices = _numVertices;
edge = _edge;
dist = new float[numVertices];
path = new int[numVertices];
S = new int[numVertices];
}

/**
* dist[j], 0<=j<n,是当前求到的从顶点v到顶点j的最短路径长度; path[j], 0<=j<n,存放求到的最短路径
*
* @param n
* @param v
*/
public void ShortestPath(int n, int v) {
for (int i = 0; i < n; i++) { // dist和path数组初始化
dist[i] = edge[v][i]; // 邻接矩阵第v行元素复制到dist中
S[i] = 0; // 已求出最短路径的顶点集合初始化
if (i != v && dist[i] < MAXNUM) {
path[i] = v;
} else {
path[i] = -1; // 路径存放数组初始化
}
}

S[v] = 1; // 顶点v加入顶点集合
dist[v] = 0;
for (int i = 0; i < n - 1; i++) { // 从顶点v确定n-1条路径
float min = MAXNUM;
int u = v;
for (int j = 0; j < n; j++) { // 选择当前不在集合S中具有最短路径的顶点u
if (S[j] == 0 && dist[j] < min) {
u = j;
min = dist[j];
}
}

S[u] = 1; // 将顶点u加入集合S,表示它已在最短路径上
for (int w = 0; w < n; w++) { // 修改
if (S[w] == 0 && (edge[u][w] < MAXNUM)
&& (dist[u] + edge[u][w] < dist[w])) {
dist[w] = dist[u] + edge[u][w];
path[w] = u;
}
}
}
}

/**
* 获得顶点表
*
* @return
*/
public int getNumVertices() {
return numVertices;
}

/**
* 获得邻接矩阵
*
* @return
*/
public float[][] getEdge() {
return edge;
}

/**
* dist[j], 0<=j<n,是当前求到的从顶点v到顶点j的最短路径长度;
*
* @return
*/
public float[] getDist() {
return dist;
}

/**
* path[j], 0<=j<n,存放求到的最短路径
*
* @return
*/
public int[] getPath() {
return path;
}

/**
* 已求得的在最短路径上的顶点的定点号
*
* @return
*/
public int[] getS() {
return S;
}

}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值