在準備ACM比賽的過程當中,研究了圖論中一些算法。首先研究的即是最短路的問題。《離散數學》第四版(清華大學出版社)一書中講解的Dijkstra算法是我首先研究的源材料。java
java實現的方式以下: 數組
第一步,根據圖來創建權值矩陣:ide
int[][] W = {
{ 0, 1, 4, -1, -1, -1 },
{ 1, 0, 2, 7, 5, -1 },
{ 4, 2, 0, -1, 1, -1 },
{ -1, 7, -1, 0, 3, 2 },
{ -1, 5, 1, 3, 0, 6 },
{ -1, -1, -1, 2, 6, 0 } };(-1表示兩邊不相鄰,權值無限大)學習
例如:W[0][2]=4 表示點V0到點V2的權值爲4測試
W[0][3]=-1表示點V0與V3不相鄰,因此權值無限大。spa
第二步:對V0標號;V0到其它點的路徑獲得 distance: {0,1,4,-1,-1,-1}; 找到V0到各點中權值最小的那個點(標號的點除外,-1表明無限大),故獲得1即對應的下標1,獲得V1;對V1標號,而後更改V0經過V1到其它點的路徑獲得 distance: { 0, 1, 3, 8, 6, -1}; blog
第三步:找到distance中權值最小的那個點,(標號的點除外)獲得V2,對V2標號,而後更改V0經過V1->V2到其它點的路徑獲得 distance: { 0, 1, 3, 8, 4, -1}; get
第四步:找到distance中權值最小的那個點,(標號的點除外)獲得V4,對V4標號,而後更改V0經過V1->V2到其它點的路徑獲得 distance: { 0, 1, 3, 7, 4, 10}; 數學
第四步:找到distance中權值最小的那個點,(標號的點除外)獲得V3,對V3標號,而後更改V0經過V1->V2到其它點的路徑獲得 distance: { 0, 1, 3, 7, 4, 9};
最後只剩下V5沒有被標號,就找到V5了。結束!
源代碼以下:
- package com.xh.Dijkstra;
- //這個算法用來解決無向圖中任意兩點的最短路徑
- public class ShortestDistanceOfTwoPoint_V5 {
- public static int dijkstra(int[][] W1, int start, int end) {
- boolean[] isLabel = new boolean[W1[0].length];// 是否標號
- int[] indexs = new int[W1[0].length];// 全部標號的點的下標集合,以標號的前後順序進行存儲,其實是一個以數組表示的棧
- int i_count = -1;//棧的頂點
- int[] distance = W1[start].clone();// v0到各點的最短距離的初始值
- int index = start;// 從初始點開始
- int presentShortest = 0;//當前臨時最短距離
- indexs[++i_count] = index;// 把已經標號的下標存入下標集中
- isLabel[index] = true;
- while (i_count<W1[0].length) {
- // 第一步:標號v0,即w[0][0]找到距離v0最近的點
- int min = Integer.MAX_VALUE;
- for (int i = 0; i < distance.length; i++) {
- if (!isLabel[i] && distance[i] != -1 && i != index) {
- // 若是到這個點有邊,而且沒有被標號
- if (distance[i] < min) {
- min = distance[i];
- index = i;// 把下標改成當前下標
- }
- }
- }
- if (index == end) {//已經找到當前點了,就結束程序
- break;
- }
- isLabel[index] = true;//對點進行標號
- indexs[++i_count] = index;// 把已經標號的下標存入下標集中
- if (W1[indexs[i_count - 1]][index] == -1
- || presentShortest + W1[indexs[i_count - 1]][index] > distance[index]) {
- // 若是兩個點沒有直接相連,或者兩個點的路徑大於最短路徑
- presentShortest = distance[index];
- } else {
- presentShortest += W1[indexs[i_count - 1]][index];
- }
- // 第二步:將distance中的距離加入vi
- for (int i = 0; i < distance.length; i++) {
- // 若是vi到那個點有邊,則v0到後面點的距離加
- if (distance[i] == -1 && W1[index][i] != -1) {// 若是之前不可達,則如今可達了
- distance[i] = presentShortest + W1[index][i];
- } else if (W1[index][i] != -1
- && presentShortest + W1[index][i] < distance[i]) {
- // 若是之前可達,但如今的路徑比之前更短,則更換成更短的路徑
- distance[i] = presentShortest + W1[index][i];
- }
- }
- }
- //若是所有點都遍歷完,則distance中存儲的是開始點到各個點的最短路徑
- return distance[end] - distance[start];
- }
- public static void main(String[] args) {
- // 創建一個權值矩陣
- int[][] W1 = { //測試數據1
- { 0, 1, 4, -1, -1, -1 },
- { 1, 0, 2, 7, 5, -1 },
- { 4, 2, 0, -1, 1, -1 },
- { -1, 7, -1, 0, 3, 2 },
- { -1, 5, 1, 3, 0, 6 },
- { -1, -1, -1, 2, 6, 0 } };
- int[][] W = { //測試數據2
- { 0, 1, 3, 4 },
- { 1, 0, 2, -1 },
- { 3, 2, 0, 5 },
- { 4, -1, 5, 0 } };
- System.out.println(dijkstra(W1, 0,4));
- }
- }
若是須要求無向圖各個點的最短距離矩陣,則屢次運用dijkstra算法就能夠了,代碼以下:
- package com.xh.Dijkstra;
- //這個程序用來求得一個圖的最短路徑矩陣
- public class ShortestDistance_V4 {
- public static int dijkstra(int[][] W1, int start, int end) {
- boolean[] isLabel = new boolean[W1[0].length];// 是否標號
- int min = Integer.MAX_VALUE;
- int[] indexs = new int[W1[0].length];// 全部標號的點的下標集合
- int i_count = -1;
- int index = start;// 從初始點開始
- int presentShortest = 0;
- int[] distance = W1[start].clone();// v0到各點的最短距離的初始值
- indexs[++i_count] = index;// 把已經標號的下標存入下標集中
- isLabel[index] = true;
- while (true) {
- // 第一步:標號v0,即w[0][0]找到距離v0最近的點
- min = Integer.MAX_VALUE;
- for (int i = 0; i < distance.length; i++) {
- if (!isLabel[i] && distance[i] != -1 && i != index) {
- // 若是到這個點有邊,而且沒有被標號
- if (distance[i] < min) {
- min = distance[i];
- index = i;// 把下標改成當前下標
- }
- }
- }
- if (index == end) {
- break;
- }
- isLabel[index] = true;
- indexs[++i_count] = index;// 把已經標號的下標存入下標集中
- if (W1[indexs[i_count - 1]][index] == -1
- || presentShortest + W1[indexs[i_count - 1]][index] > distance[index]) {
- presentShortest = distance[index];
- } else {
- presentShortest += W1[indexs[i_count - 1]][index];
- }
- // 第二步:獎distance中的距離加入vi
- for (int i = 0; i < distance.length; i++) {
- // 若是vi到那個點有邊,則v0到後面點的距離加
- // 程序到這裏是有問題滴! 呵呵
- if (distance[i] == -1 && W1[index][i] != -1) {// 若是之前不可達,則如今可達了
- distance[i] = presentShortest + W1[index][i];
- } else if (W1[index][i] != -1
- && presentShortest + W1[index][i] < distance[i]) {
- // 若是之前可達,但如今的路徑比之前更短,則更換成更短的路徑
- distance[i] = presentShortest + W1[index][i];
- }
- }
- }
- return distance[end] - distance[start];
- }
- public static int[][] getShortestPathMatrix(int[][] W) {
- int[][] SPM = new int[W.length][W.length];
- //屢次利用dijkstra算法
- for (int i = 0; i < W.length; i++) {
- for (int j = i + 1; j < W.length; j++) {
- SPM[i][j] =dijkstra(W, i, j);
- SPM[j][i] = SPM[i][j];
- }
- }
- return SPM;
- }
- public static void main(String[] args) {
- /* 頂點集:V={v1,v2,……,vn} */
- int[][] W = { { 0, 1, 3, 4 }, { 1, 0, 2, -1 }, { 3, 2, 0, 5 },
- { 4, -1, 5, 0 } };
- int[][] W1 = { { 0, 1, 4, -1, -1, -1 }, { 1, 0, 2, 7, 5, -1 },
- { 4, 2, 0, -1, 1, -1 }, { -1, 7, -1, 0, 3, 2 },
- { -1, 5, 1, 3, 0, 6 }, { -1, -1, -1, 2, 6, 0 } };// 創建一個權值矩陣
- ;// 創建一個權值矩陣
- int[][] D = getShortestPathMatrix(W1);
- //輸出最後的結果
- for (int i = 0; i < D.length; i++) {
- for (int j = 0; j < D[i].length; j++) {
- System.out.print(D[i][j] + " ");
- }
- System.out.println();
- }
- }
- }
若是須要個人學習資料,我很是樂意分享;若是讀者可以有所賜教,我甚感榮幸。QQ:810050504(小帥),郵箱是QQ郵箱