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

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;
	}

}

你可能感兴趣的:(J#)