[圖論]最短網絡:prim

最短網絡


Description

農民約翰被選爲他們鎮的鎮長!他其中一個競選承諾就是在鎮上建立起互聯網,並連接到所有的農場。當然,他需要你的幫助。約翰已經給他的農場安排了一條高速的網絡線路,他想把這條線路共享給其他農場。爲了用最小的消費,他想鋪設最短的光纖去連接所有的農場。你將得到一份各農場之間連接費用的列表,你必須找出能連接所有農場並所用光纖最短的方案。每兩個農場間的距離不會超過100000


Input

第一行: 農場的個數,N(3<=N<=100)。
第二行…結尾: 後來的行包含了一個N*N的矩陣,表示每個農場之間的距離。理論上,他們是N行,每行由N個用空格分隔的數組成,實際上,他們限制在80個字符,因此,某些行會緊接着另一些行。當然,對角線將會是0,因爲不會有線路從第i個農場到它本身。


Output

只有一個輸出,其中包含連接到每個農場的光纖的最小長度。


Sample Input

4
0 4 9 21
4 0 8 17
9 8 0 16
21 17 16 0


Sample Output

28


解析

這道題一看就是最小生成樹,有兩種方法,分別爲
普里姆算法(prim

克魯斯卡爾(kruskal
本題解使用的是 prim
Prim算法採用與DijkstraBellman-Ford算法一樣的“藍白點”思想:白點代表已經進入最小生成樹的點,藍點代表未進入最小生成樹的點。


代碼

#include<stdio.h>
#include<string.h>
#include<iostream>
using namespace std;
int n,o,a[1005][105],u[105],minn[105],ans; //a是連接矩陣,u是判斷是藍點(1)或白點(0),minn是最小生成樹的最小邊權
int main(){ //prim是以1爲起點
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		for(int j=1;j<=n;j++)
			scanf("%d",&a[i][j]);
	memset(minn,0x7f,sizeof(minn)); //把minn全部改爲maxint
	minn[1]=0; //唯有minn[1]是0,因爲自己到自己的距離爲0
	memset(u,1,sizeof(u)); //全部標記爲1(藍點)
	for(int i=1;i<=n;i++){
		o=0; 
		for(int j=1;j<=n;j++)
			if(u[j] and (minn[j]<minn[o])) //u[j]判斷這個點是不是藍點,再看是是不是最小邊權
				o=j;
		u[o]=0; //加入最小生成樹,標記爲白點
		for(int j=1;j<=n;j++)
			if(u[j] and (a[o][j]<minn[j])){ //修改和o相連的白點的邊
				minn[j]=a[o][j];
			}
				
	}
	for(int i=1;i<=n;i++)
		ans+=minn[i]; //累加每一條邊的權值
	printf("%d",ans);
	return 0;
} 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章