import java.io.IOException;
import java.util.Scanner;
public class Graph {
private char[] vertex; //頂點集合
private int[][] matrix; //鄰接矩陣
private static final int INF = Integer.MAX_VALUE; //最大值
/**
* 創建圖
*/
public Graph() {
Scanner sca = new Scanner(System.in);
int vertexNum = sca.nextInt(); //頂點數
int matrixNum = sca.nextInt(); //邊數
vertex = new char[vertexNum];
//初始化頂點
for(int i = 0; i < vertexNum; i++) {
vertex[i] = readChar();
}
//初始化 邊 的權值
matrix = new int [vertexNum][vertexNum];
for(int i = 0; i < vertexNum; i++)
for(int j = 0; j < vertexNum; j++)
matrix[i][j] = (i == j) ? 0 : INF;
//根據用戶輸入的邊的信息:初始化邊
for(int i = 0; i < matrixNum; i++) {
char start = readChar();
char end = readChar();
int weight = sca.nextInt();
int startInedx = getLocation(start);
int endIndex = getLocation(end);
if(startInedx == -1 || endIndex == -1) return;
matrix[startInedx][endIndex] = weight;
matrix[endIndex][startInedx] = weight;
}
sca.close();
}
/**
* 返回字符的位置
*/
private int getLocation(char c) {
for(int i = 0; i < vertex.length; i++)
if(vertex[i] == c) return i;
return -1;
}
/**
* 讀取一個輸入字符
* @return
*/
private char readChar() {
char ch = '0';
do {
try {
ch = (char)System.in.read();
} catch (IOException e) {
e.printStackTrace();
}
}while(!((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')));
return ch;
}
/**
* 打印矩陣隊列圖
*/
public void print() {
for(int i = 0; i < vertex.length; i++)
for(int j = 0; j < vertex.length; j++)
System.out.printf("%10d", matrix[i][j]);
System.out.println();
}
public void prim(int start) {
int num = vertex.length; //頂點個數
int index = 0; //prim最小的索引,即prims數組的索引
char[] prims = new char[num];//prim最小樹的結果
int[] weights = new int[num];//頂點間邊的權值
//prim最小生成樹中的第一個數是 "圖中第start個頂點",因爲是從strat開始的
prims[index++] = vertex[start];
//初始化"頂點的權值數組"
//將每個頂點的權值初始化爲第start個頂點 到"該頂點"的權值
for(int i = 0; i < num; i++)
weights[i] = matrix[start][i];
//自己到自己的路徑爲0
weights[start] = 0;
for(int i = 0; i < num; i++) {
//由於從start開始的,因此不再需要再第start個頂點進行處理
if(start == i) continue;
int j = 0;
int k = 0;
int min = INF;
//在未被加入到最小生成樹的頂點中,找出權值最小的頂點
while(j < num) {
//若weights[j]=0,意味着"第j個節點已經被排序過"(或者說已經加入了最小生成樹中)
if(weights[j] != 0 && weights[j] < min) {
min = weights[j];
k = j;
}
j++;
}
// 經過上面的處理後,在未被加入到最小生成樹的頂點中,權值最小的頂點是第k個頂點。
// 將第k個頂點加入到最小生成樹的結果數組中
prims[index++] = vertex[k];
//將"第k個頂點的權值"標記爲0,意味着第k個頂點已經排序過了(或者說已經加入了最小樹結果中)
weights[k] = 0;
// 當第k個頂點被加入到最小生成樹的結果數組中之後,更新其它頂點的權值。
for(j = 0; j < num; j++) {
//當第j個節點沒有被處理,並且需要更新的時才更新
if(weights[j] != 0 && matrix[k][j] < weights[j])
weights[j] = matrix[k][j];
}
}
//計算最小生成樹的權值
int sum = 0;
for(int i = 1; i < index; i++) {
int min = INF;
//獲取prims[i]在matrix中的位置
int n = getLocation(prims[i]);
// 在vertex[0...i]中,找出到j的權值最小的頂點
for(int j = 0; j < i; j++) {
int m = getLocation(prims[j]);
if(matrix[m][n] < min) {
min = matrix[m][n];
}
}
sum +=min;
}
//打印最小生成樹
System.out.print("PRIM(" + vertex[start] + ") = " + sum);
for(int i = 0; i < index; i++)
System.out.print(prims[i]);
System.out.println();
}
public static void main(String[] args) {
Graph ga = new Graph();
ga.prim(0);
}
}
普里姆算法
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.