【九度OJ】1008【加权无向图最短路径】

在网上查了一下,加权无向图最短路解法DFS和Dijkstra多一些,一般不用BFS

我选择用DFS,用时380MS,看了一下其他人的,最好的是240MS,用的是Dijkstra。都是采用邻接矩阵存储图结构。

在DFS的过程中,开始我的做法是,每找到一条从s到t的路径就存储起来,最后将最优路径输出。后来优化一下,在找路径的过程中,即DFS方法内部就可以判断出来(通过设置全局变量),这样最后DFS方法返回后,直接输出最短路径就可以。

DFS和Dijkstra的时间区别就在于核心方法DFS和Dijkstra上,所以还是Dijkstra优一些。这些算法要以后慢慢练习啦,比如之前的快排,今天遇到的Dijkstra,练习一次就好了。

代码:

package Test1;

import java.util.Scanner;

public class Test53 {

	/**
	 * by qr jobdu 1008 2014-8-7(8) graph:shortest path
	 */
	static int mind=Integer.MAX_VALUE;
	static int minp=Integer.MAX_VALUE;
	
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		int n, m;
		n = scan.nextInt(); // number of node
		m = scan.nextInt(); // number of edge

		while (!(n == 0 && m == 0)) {
			int edgeD[][] = new int[n + 1][n + 1]; // node number is 1-->n
			int edgeP[][] = new int[n + 1][n + 1];

			boolean flag[] = new boolean[n + 1]; // flag node pass situation(不要忘记加一个标记数组记录节点是否被访问过,迷宫也一样)

			for (int i = 1; i < n + 1; i++) {
				flag[i] = false;
				for (int j = 1; j < n + 1; j++)
					edgeD[i][j] = 0; // 0 represent no edge
			}

			for (int i = 0; i < m; i++) {
				int a = scan.nextInt();
				int b = scan.nextInt();

				edgeD[a][b] = scan.nextInt();
				edgeD[b][a] = edgeD[a][b];

				edgeP[a][b] = scan.nextInt();
				edgeP[b][a] = edgeP[a][b];
			}

			int s = scan.nextInt();
			int t = scan.nextInt();

			// dfs get the shortest path
			flag[s] = true;
			DFS(s, t, edgeD, edgeP, n, 0, 0, flag);
			
			//output result
			System.out.println(mind+" "+minp);
			
			mind=Integer.MAX_VALUE;  //!important
			minp=Integer.MAX_VALUE;
			
			n = scan.nextInt();
			m = scan.nextInt();
			
			
		}
	}

	private static void DFS(int a, int b, int[][] edgeD, int[][] edgeP, int n,
			int d, int p, boolean flag[]) {
		if (a == b) {
			//在过程中就可以判断出来最小的,而无需返回再判断
			if(mind>d || (mind==d && minp>p)){
				mind=d;
				minp=p;
			}
		} else {
			for (int i = 1; i < n + 1; i++) {
				if (edgeD[a][i] != 0 && !flag[i]) {  //flag[i]=false
					flag[i] = true;
					DFS(i, b, edgeD, edgeP, n, d + edgeD[a][i],
							p + edgeP[a][i], flag);
					flag[i]=false; //访问之后记得将状态变回来,无需创建一个一样大小的数组
				}
			}
		}
	}

}

通过这道题,我也得到了一些经验:

1.当每次while结束时,要将全局变量重新赋值

2.需要一个非常大的数的时候,使用Integer.MAX_VALUE

3.DFS找最短路径,要设置一个flag变量。递归找路径一般都需要设这样一个标记结点是否被访问的数组,如DFS,迷宫。而当访问过后,因为还需要找其他路径,所以不要忘记将flag变回false

我觉得这样练习OJ真的可以提高自己的编程能力,获得编程经验,继续加油!

你可能感兴趣的:(jobdu(JAVA实现))