码迷,mamicode.com
首页 > 其他好文 > 详细

杭电ACM1162——Eddy's picture~~最小生成树

时间:2015-05-02 12:33:32      阅读:119      评论:0      收藏:0      [点我收藏+]

标签:acm   杭电   kruskal   

这一题,就是简单的最小生成树的应用。开始,没有想到用最小生成树做,想到的是贪心,当知道了用最小生成树做的时候,还犯了一个很严重的错误,就是时间复杂度的估计错了,导致开始不敢写,在想其他的办法。当作一次教训吧。

下面是AC的代码,有详细的注释,用的是并查集来判环,时间复杂度为nlogn,主要时间在排序上。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;

class data                      //每两个点直接的边的数据
{
public:
	int from, to;               //起点与终点
	double dis;                 //距离
};
data Dis[15000];                //最多边的时候,大概接近10000
double xy[105][2];
int par[105], n, m;             //par为并查集

int cmp(const data& a, const data& b)  //排序按距离从小到大排
{
	return a.dis < b.dis;
}

int finds(int x)                //并查集查找函数
{
	if(x == par[x])
		return x;
	else
		return par[x] = finds(par[x]);
}
void join(int x, int y)        //并查集合并函数
{
	x = finds(x);
	y = finds(y);
	if(x != y)
		par[y] = x;
}

double kru()                   //kruskal算法
{
	for(int i = 0; i <= n; i++)  //初始化并查集
	{
		par[i] = i;
	}
	sort(Dis, Dis + m, cmp);     //排序
	double ans = 0.0;
	for(int j = 0; j < m; j++)
	{
		if(finds(Dis[j].from) != finds(Dis[j].to))   //判是否存在环
		{
			ans += Dis[j].dis;
			join(Dis[j].from, Dis[j].to);            //合并两点
		}
	}
	return ans;
}

int main()
{
	while(scanf("%d", &n) != EOF)
	{
		m = 0;
		for(int i = 0; i < n; i++)
		{
			scanf("%lf%lf", &xy[i][0], &xy[i][1]);
		}
		for(int j = 0; j < n; j++)                 //求每两点之间的距离
		{
			for(int k = j + 1; k < n; k++)
			{
				Dis[m].from = j;
				Dis[m].to = k;
				Dis[m++].dis = sqrt(pow((xy[j][0] - xy[k][0]), 2) + pow((xy[j][1] - xy[k][1]), 2));
			}
		}
		double ans = kru();
		printf("%.2lf\n", ans);                 //这里用C++提交的,如果用G++,应该改成 %.2f
	}
	return 0;
}


杭电ACM1162——Eddy's picture~~最小生成树

标签:acm   杭电   kruskal   

原文地址:http://blog.csdn.net/qq_25425023/article/details/45438369

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!