[圖論]劍魚行動:prim

劍魚行動


Description

給出N個點的座標,對它們建立一個最小生成樹,代價就是連接它們的路徑的長度,現要求總長度最小。N的值在100以內,座標值在[-10000,10000].結果保留二位小數


Input

N個點 ,N個點的座標


Output

連接它們的最短路徑的長度


Sample Input

5 ---------------5個點
0 0 ---------------5個點點的座標
0 1
1 1
1 0
0.5 0.5


Sample Output

2.83


解析

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

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


難點

題目給出的可能是小數,所以就有了我們的讀入方式
aj[i][1]儲存x座標,a[j][2]儲存y座標

for(int i=1;i<=n;i++)scanf("%lf%lf",&aj[i][1],&aj[i][2]);

以及我們的計算距離公式,原理是勾股定理

sqrt((abs(aj[i][1]-aj[j][1]))*(abs(aj[i][1]-aj[j][1]))+(abs(aj[i][2]-aj[j][2]))*(abs(aj[i][2]-aj[j][2])));

代碼

模板解析

#include<cmath>
#include<stdio.h>
#include<iostream>
using namespace std;
int n,u[10005],o,p,q;
double ans,minn[10005],aj[10005][3],a[10005][10005];
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++)scanf("%lf%lf",&aj[i][1],&aj[i][2]); //神奇的讀入
	for(int i=1;i<=n;i++){ //神奇的處理
		for(int j=1;j<n;j++){
			a[i][j]=sqrt((abs(aj[i][1]-aj[j][1]))*(abs(aj[i][1]-aj[j][1]))+(abs(aj[i][2]-aj[j][2]))*(abs(aj[i][2]-aj[j][2])));
			a[j][i]=a[i][j];
		}
	}
	memset(minn,0x7f,sizeof(minn)); //愉快地套我們的模板,解析鏈接在上面
	minn[1]=0;
	memset(u,true,sizeof(u));
	for(int i=1;i<=n;i++){
		o=false;
		for(int j=1;j<=n;j++)
			if(u[j] and (minn[j]<minn[o]))
				o=j;
		u[o]=0;
		for(int j=1;j<=n;j++)
			if(u[j] and (a[o][j]<minn[j])){
				minn[j]=a[o][j];

			}
				
	}
	for(int i=1;i<=n;i++)
		ans+=minn[i];
	printf("%.2lf",ans);
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章