1. 程式人生 > >YTU.1012: A MST Problem

YTU.1012: A MST Problem

1012: A MST Problem

時間限制: 1 Sec  記憶體限制: 32 MB
提交: 56  解決: 30
[提交][狀態][討論版][命題人:外部匯入]

題目描述

It is just a mining spanning tree ( 最小生成樹 ) problem, what makes you a little difficult is that you are in a 3D space.

輸入

The first line of the input contains the number of test cases in the file. And t he first line of each case

contains one integer numbers n(0<n<30) specifying the number of the point . The n next n line s, each line

contain s Three Integer Numbers xi,yi and zi, indicating the position of point i.

輸出

For each test case, output a line with the answer, which should accurately rounded to two decimals .

樣例輸入

2
2
1 1 0
2 2 0
3
1 2 3
0 0 0
1 1 1

樣例輸出

1.41
3.97

分析:3D空間上的最小生成樹問題,

一個三維座標點可以看成最小生成樹的一個節點,那麼三維空間裡的點與點之間的距離就可以看成這兩個節點間邊的權重。

可以用結構體儲存各個點的座標x,y,z;


太菜了,沒能寫出來prim演算法....還是繼續用比較好寫的kruskal演算法吧。

#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<memory.h> 
using namespace std;
const int maxn=35;
double mp[maxn][maxn];
int f[maxn];
typedef struct {
	int x;
	int y;
	int z;
} ZB;
ZB a[maxn];
typedef struct {
	int x;
	int y;
	double w;
} QQ;
QQ b[maxn];
bool cmp(QQ a,QQ b) {
	return a.w<b.w;
}
int findx(int x) {
	int r=x;
	while(r!=f[r])
		r=f[r];
	return r;
}
int main() {
	int t,n;
	cin>>t;
	while(t--) {
		cin>>n;
		for(int i=1; i<=n; i++) {
			cin>>a[i].x>>a[i].y>>a[i].z;
			f[i]=i;
		}
		memset(mp,0,sizeof(mp));//初始化 
		double len;
		for(int i=1; i<=n; i++) {
			for(int j=i+1; j<=n; j++) {
				len=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)+(a[i].z-a[j].z)*(a[i].z-a[j].z));
				mp[i][j]=mp[j][i]=len;//構造鄰接矩陣
			}
		}
//		for(int i=1;i<=n;i++)
//		{
//			for(int j=1;j<=n;j++)
//	{
//		cout<<mp[i][j]<<" ";
//	}
//		cout<<endl;
//		}
		int q=0;
		for(int i=1; i<=n; i++)
			for(int j=1; j<=n; j++) {
				if(j>i) {
					q++;
					b[q].x=i;
					b[q].y=j;
					b[q].w=mp[i][j];
				}
			}
		sort(b+1,b+q+1,cmp);
		int p=0;
		double ans=0;
		for(int i=1; i<=q; i++) {
			if(findx(b[i].x)!=findx(b[i].y)) {
				ans+=b[i].w;
				f[findx(b[i].x)]=b[i].y;
				p++;
				if(p==n-1)
					break;
			}
		}
		printf("%.2lf\n",ans);
	}
	return 0;
}

prim演算法:

#include<bits/stdc++.h>
using namespace std;
#define maxn 35
#define INF 999999
double graph[maxn][maxn];//鄰接矩陣
double dist[maxn];//距離
bool vis[maxn];
typedef struct{
	int x;
	int y;
	int z;
}ZB;
ZB a[maxn];
int N;
double prim()
{
	int pos=1;
	double ans,Min;
	memset(vis,0,sizeof(vis));
	ans=0;
	for(int i=1;i<=N;i++)
	{
		dist[i]=graph[pos][i];//與pos鄰接點的距離
	}
	vis[pos]=1;
	for(int i=2;i<=N;i++)
	{
		Min=INF;
		pos=-1;
		for(int j=1;j<=N;j++)
		{
			if(!vis[j]&&Min>dist[j])
			{
				Min=dist[j];
				pos=j;
			}
		}
			if(pos==-1)
			return -1;
			vis[pos]=1;
			ans+=Min;
			for(int j=1;j<=N;j++)
			{
				if(!vis[j]&&dist[j]>graph[pos][j])//執行更新,如果點距離當前點的距離更近,就更新dist
				dist[j]=graph[pos][j];
			}
	}
	return ans;
}
int main()
{
	int t,n;
	cin>>t;
	while(t--) {
		cin>>n;
		N=n;
		for(int i=1;i<=N;i++)
		for(int j=1;j<=N;j++)
		{
			graph[i][j]=INF;//初始化均不可達
		}
		for(int i=1; i<=n; i++) {
			cin>>a[i].x>>a[i].y>>a[i].z;
		}
		double len;
		for(int i=1; i<=n; i++) {
			for(int j=i+1; j<=n; j++) {
				len=sqrt((a[i].x-a[j].x)*(a[i].x-a[j].x)+(a[i].y-a[j].y)*(a[i].y-a[j].y)+(a[i].z-a[j].z)*(a[i].z-a[j].z));
				graph[i][j]=graph[j][i]=len;//構造鄰接矩陣
			}
		}
    printf("%.2lf\n",prim());
	}
	return 0;
}