這是乙個有感情的演算法,十分的精巧和可愛,哈哈,我是這樣感覺的。
要了解什麼是普里姆,你需要一丟丟的圖論和樹的知識。
①明白普里姆的使用目的,就是構造一棵最小生成樹。那麼什麼是最小生成樹呢,顧名思義,最小生成樹的概念是建立在生成樹的概念上的,也就是說,你得明白什麼是生成樹。生成樹是指包含乙個圖種所有的n個點,但是只含有n-1條邊,也就是這個圖的最小連通子圖。如果你構成了乙個生成樹,那麼你捏住其中乙個點,可以將這個圖中所有的點拉起來,同時你捏住的點就是這顆樹的根節點,是不是很神奇。
②有了生成樹的概念那麼你就大概知道最小生成樹的概念了,那就是使得鏈結所有的點的邊的權值最小,那麼這裡什麼是權值呢,題主一開始看見權值也是一臉懵逼啊,其實很簡單,其實就是邊的長度或者這條邊代表的意義,比如你這條邊如果指的是一條路,那麼權值可以是長度也可以是修路的費用。恩,最小生成樹的概念就出來了呀。那麼你要怎麼求出來呢。
③噠噠噠,神奇的普里姆演算法就來了。普里姆在一定意義上講是一種貪心的思想。你想想看,要使你取的所有邊都是最小的,那麼你要做的就是每次都取最小的邊啊,對不對。沒錯就是這樣,看圖
看到圖了不,一開始你可以任意取得乙個點,這裡假設是v1點,v1的相連著3條邊,那麼你要選擇那一條呢,就想起上面說過的,我們要貪心,那就選擇最短的,就是 1 ,好的,選擇了這條邊的結果是使得v1和v3相連了,那我們是不是接著判斷v3的所有邊的最短的呢,先等等,我們是不是忘記了什麼,是啊,你們把v1忘記了,所以當你鏈結乙個點的時候要判斷的是連線起來的部分和剩下的部分最短的路徑,所以這裡就要時時的更新你的最短路徑。這樣就不會有其他的錯誤了吧。沒錯,你要做的就是重複上面的操作啦,只要重複n-1次,為什麼呢,這要結合具體程式講解。
來設定陣列map[100][100] //這是用來存圖的陣列,存圖有多種方式,鄰接矩陣,鄰接表等這裡先不講。
還需要乙個最短路徑的儲存陣列 dis[100] //這個其實主要用於更新路徑的
最後還需要乙個標記陣列 visit[100] //標記已經被鏈結的點
好的接下來是**:
#define inf 1e9+7
int prim(int num,int *a)
; // 標誌陣列的設定
int sum=0,min,min_i;
for(int i=0;i
visit[0]=1;
for(o=1;o
}if(min==inf)
break;
sum+=min;
visit[min_i]=1;
for(i=0;i
if(visit[i]==0&&dis[i]>a[min_i][i])}}
}這個結果的展示結合具體題目
杭電1102題
題意是要你實現這樣的程式,給你乙個n,這是所給村莊的數目,然後是乙個鄰接矩陣,這個矩陣會給你村莊之間的路徑長度,同時還會輸入乙個m,這是已經修好的路,會告訴你是那兩個村莊之間的。要你求解,使得每乙個村莊之間都相連所要修的最短路徑。
這顯然是乙個求最短路徑的問題,那麼你是不是想到了我們的普里姆呢,是不是很合適啊,最小生成樹一套,完美啊。
那麼看**:
#include
#include
#include
#include
#include
#define inf 1e9+7
using namespace std;
int main()
}scanf("%d",&m);
for(i=0;i
s[0]=1;
for(i=0;i
for(o=1;o
}if(u==inf)
break;
sum+=u;
s[y]=1;
for(i=0;i
}printf("%d\n",sum);
}return 0;
}噠噠噠,完成。
普里姆演算法
include include include include using namespace std define max name 5 define max vertex num 20 權的上限值 typedef char vertex max name 頂點名字串 typedef int ad...
普里姆演算法
普里姆演算法的基本思想如下 假設n 是連通網,te是n上最小生成樹中邊的集合。從u 開始,te 開始,重複執行下述操作 在所有的u屬於u,v屬於v u的邊 u,v 的邊中找到權值最小的一條邊,並且併入te,同時u併入u,直到u v 先設乙個輔助陣列closedge max 初始時先把第乙個結點存入c...
普里姆演算法
include include include using namespace std define maxint 32767 define maxnum 100 typedef struct vnode,closedge maxnum typedef struct amgraph intlocat...