贪婪算法在求解最小生成树中的应用(JAVA)--Prim算法
貪婪算法:通過一系列步驟來構造問題的解,每一步對目前構造的部分分解做一個拓展,直到獲得問題的完整解為止,而算法的核心思想就在于,算法的每一步都必須滿足以下條件:可行(滿足問題的約束條件)、局部最優(當前步驟所有可行選擇中的局部最優解)、不可取消(一旦選擇,在后續步驟中不可改變)。
對于連通圖來說生成樹定義為包含圖中所有頂點的連通無環子圖
而在加權連通圖中權重最小的生成樹被稱為最小生成樹
Prim算法被又稱為“加點法”,我們從圖中的頂點集合中任意選擇一個頂點作為序列的初始子樹,每次迭代的時候,以貪婪的方式擴張生成樹,該算法每次只擴展一個點,迭代的總次數為n-1。所以這就要求對于每個不在樹中的頂點,必須知道它連接樹中頂點的最短邊信息。我們可以給一個頂點附加兩個標記:樹中最近頂點的名稱以及對應邊的長度。對于任意加入生成樹中的頂點來說,我們要做兩步,操作一:將該頂點從集合V-Vt 移動帶頂點集合Vt中,操作二:對V-Vt中的每個頂點更新。
我們以下面這個圖為例子講解Prim算法的過程:
Input:
6 10
1 2 3
1 5 6
1 6 5
2 6 5
2 3 1
3 6 4
3 4 6
4 6 5
4 5 8
5 6 2
Output:
15
完整代碼如下:
import java.util.Scanner;public class Main {static int[][] e = new int[7][7];static int[] book = new int[7];static int[] dis = new int[7];static int count = 0;static int sum = 0;static int n, m;static int min, mark;static Scanner input = new Scanner(System.in);public static void main(String[] args) {n = input.nextInt();m = input.nextInt();for (int i = 1; i <= n; i++) {for (int j = 1; j <= n; j++) {if (i == j) {e[i][j] = 0;} else {e[i][j] = 99999999;}}}for (int i = 1; i <= m; i++) {int a = input.nextInt();int b = input.nextInt();int c = input.nextInt();e[a][b] = c;e[b][a] = c;}for (int i = 1; i <= n; i++) {dis[i] = e[1][i];}book[1] = 1;prime();System.out.println(sum);}private static void prim() {count++;while (count < n) {min = 99999999;for (int i = 1; i <= n; i++) {if (book[i] == 0 && dis[i] < min) {min = dis[i];mark = i;}}book[mark] = 1;count++;sum += dis[mark];for (int i = 1; i <= n; i++) {if (book[i] == 0 && dis[i] > e[mark][i]) {dis[i] = e[mark][i];}}}} }時間復雜度O(n^2),如果采用堆來構造一個優先隊列則會使算法的時間復雜度變為O(nlogn)
很感興趣的讀者可以參考圖論算法(四)--最小生成樹的Kruskal [ 加邊 ] 、Prim [ 加點 ] 的解法(JAVA)這篇文章
總結
以上是生活随笔為你收集整理的贪婪算法在求解最小生成树中的应用(JAVA)--Prim算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 减治法在生成全排列中的应用(JAVA)-
- 下一篇: FAIL : SSHException: