UVA:10034 - Freckles

本文介绍如何使用kruskal算法解决求最小生成树的问题,并提供了详细的代码实现,包括点与点距离计算、kruskal算法流程、初始化、查找路径和并查集操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&category=116&page=show_problem&problem=975

典型的求最小生成树的题目,采用kruskal算法即可,先存储所有的点,然后分别计算点与点之间的距离,并存储起来,在直接运用kruskal算法即可。唯一需要注意的是输出格式问题。代码如下:

/*
ID: csuchenan
PROG: uva10034Freckles
LANG: C++
*/

#include<iostream>
#include<stdio.h>
#include<stdlib.h>
#include<math.h>

using namespace std ;

const int maxn = 105 ;

struct Point
{
	double x ;
	double y ;
}point[maxn] ;

struct Edge
{
	int x ;
	int y ;
	double dist ;
}edge[5000] ;

int parent[maxn] ;

double distance_point ( Point x , Point y)
{
	return sqrt((x.x - y.x) * (x.x - y.x) + (x.y - y.y) * (x.y - y.y)) ;
}

int cmp(const void * a , const  void * b)
{
	return (*(Edge *)a).dist > (*(Edge *)b).dist ;
}

double kruskal() ;

void init() ;
int find_x(int x) ;
void join(int x , int y) ;

int num  ;
int nnum ;
int main()
{
//	freopen("10034.in" , "r" , stdin) ;
	
	int tests ;
	scanf("%d" , &tests) ;
	while(tests--)
	{
		scanf("%d" , &num) ;
	
		int i ;
		i = 0 ;
	
		while(i < num)
		{
			scanf("%lf %lf" , &point[i].x , &point[i].y) ;
			i ++ ;
		}
	
		int j ;
	
		int k ;
		k = 0 ;
	
		for(i = 0 ; i < num ; i ++)
		{
			for(j = i + 1 ; j < num ; j ++)
			{		
				edge[k].x = i ;
				edge[k].y = j ;
			
				edge[k].dist = distance_point(point[i] , point[j]) ;	
			
				k ++ ;
			}
		}
	
		nnum = k ;
		
		printf("%.2f\n" , kruskal()) ;
		
		if(tests >= 1)
			printf("\n") ;
	}
	return 0 ;
}

void init()
{	
	int i ;
	
	for(i = 0 ; i < num ; i ++)
	{
		parent[i] = i ;
	}
}

int find_x(int x)
{
	int r = x ;
	
	while(r != parent[r])
		r = parent[r] ;
	
	int i ;
	int j ;
	
	for(i = x ; i != r ;)
	{
		j = parent[i] ;
		parent[i] = r ;
		i = j ;
	}
	
	return r ;
}

void join(int x , int y)
{
	int p = find_x(x) ;
	int q = find_x(y) ;
	
	if(p < q)
		parent[q] = p ;
	
	else 
		parent[p] = q ;	

}

double kruskal()
{
	init() ;
	
	qsort(edge , nnum , sizeof(edge[0]) , cmp) ;
	
	double sum ;
	sum = 0.0 ;
	
	int i ;
	 
	for(i = 0 ; i < nnum ; i ++)
	{
		if(find_x(edge[i].x) != find_x(edge[i].y) )
		{	
			sum += edge[i].dist ;
			join(edge[i].x , edge[i].y) ;
		}
	}
	
	return sum ;
}


 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值