月【貪心 人類智慧】
阿新 • • 發佈:2021-10-18
基本介紹
普里姆演算法(Prim演算法),圖論中的一種演算法,可在加權連通圖裡搜尋最小生成樹。意即由此演算法搜尋到的邊子集所構成的樹中,不但包括了連通圖裡的所有頂點(英語:Vertex (graph theory)),且其所有邊的權值之和亦為最小。該演算法於1930年由捷克數學家沃伊捷赫·亞爾尼克(英語:Vojtěch Jarník)發現;並在1957年由美國電腦科學家羅伯特·普里姆(英語:Robert C. Prim)獨立發現;1959年,艾茲格·迪科斯徹再次發現了該演算法。因此,在某些場合,普里姆演算法又被稱為DJP演算法、亞爾尼克演算法或普里姆-亞爾尼克演算法。
案例
1)有勝利鄉有7個村莊(A, B, C, D, E, F, G) ,現在需要修路把7個村莊連通
2)各個村莊的距離用邊線表示(權) ,比如 A – B 距離 5公里
3)問:如何修路保證各個村莊都能連通,並且總的修建公路總里程最短?
最小生成樹
這個問題本質上就是最小生成樹問題,最小生成樹:一個有 n 個結點的連通圖的生成樹是原圖的極小連通子圖,且包含原圖中的所有 n 個結點,並且有保持圖連通的最少的邊。最小生成樹可以用kruskal(克魯斯卡爾)演算法或prim(普里姆)演算法求出。
思路
程式碼
import java.util.Arrays; public class PrimAlgorithm { public static void main(String[] args) { char[] data = {'A','B','C','D','E','F','G'}; int [][]weight=new int[][]{ //10000表示不通 {10000,5,7,10000,10000,10000,2}, {5,10000,10000,9,10000,10000,3}, {7,10000,10000,10000,8,10000,10000}, {10000,9,10000,10000,10000,4,10000}, {10000,10000,8,10000,10000,5,4}, {10000,10000,10000,4,5,10000,6}, {2,3,10000,10000,4,6,10000},}; int vertex = data.length; MGraph graph = new MGraph(vertex); MinTree minTree = new MinTree(); minTree.createGraph(graph,vertex,data,weight); minTree.showGraph(graph); minTree.prim(graph,0); } } class MGraph { int vertex; //頂點個數 char[] data; //存放頂點 int[][] weight; //鄰接矩陣 public MGraph(int vertex) { this.vertex = vertex; weight = new int[vertex][vertex]; data = new char[vertex]; } } class MinTree { /** * 建立圖的鄰接矩陣 * @param graph 圖物件 * @param vertex 圖頂點個數 * @param data 圖的頂點的值 * @param weight 圖對應的鄰接矩陣 */ public void createGraph(MGraph graph,int vertex,char[] data,int[][] weight) { int i, j; for(i = 0; i < vertex; i++) { graph.data[i] = data[i]; for(j = 0; j < vertex; j++) { graph.weight[i][j] = weight[i][j]; } } } /** * 顯示圖的鄰接矩陣 * @param graph 圖物件 */ public void showGraph(MGraph graph) { for (int[] link : graph.weight) { System.out.println("link = " + Arrays.toString(link)); } } /** * 普利姆演算法 * @param graph 圖物件 * @param v 表示從哪個頂點開始 */ public void prim(MGraph graph,int v) { int[] visited = new int[graph.vertex]; //0表示未使用,1表示已使用 visited[v] = 1; int index1 = 0; int index2 = 0; int minWeight = Integer.MAX_VALUE; //假設最小權值 for (int i = 1; i < graph.vertex; i++) { for (int j = 0; j < graph.vertex; j++) { for (int k = 0; k < graph.vertex; k++) { if (visited[j] == 1 && visited[k] == 0 && graph.weight[j][k] < minWeight) { minWeight = graph.weight[j][k]; index1 = j; index2 = k; } } } System.out.println("邊為=>" + graph.data[index1] + ">" + graph.data[index2] + ",權值是" + minWeight); visited[index2] = 1; minWeight = Integer.MAX_VALUE; } } }