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

HDU ACM : 1875 畅通工程再续->最小生成树(并查集)

时间:2015-03-15 16:56:39      阅读:259      评论:0      收藏:0      [点我收藏+]

标签:acm   c++   并查集   算法   编程   

解析:最小生成树;Kruskal 算法:并查集实现。

1、首先找出符合要求的边;

2、对找出的边排序;

3、并查集找出n-1条边,无法修通n-1条路则无法实现要求。


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

struct Point
{
	int x,y;
} point[102];

struct Edge
{
	int a,b;
	double v;

	bool operator<(const Edge a)
	{
		return v<a.v;
	}
} edge[5002];

int p[102];

double Distance(Point a,Point b)
{
	return sqrt(pow(a.x-b.x,2.0)+pow(a.y-b.y,2.0));
}

bool Init(int n)                //一开始指向自己
{
	for(int i=0;i<=n;i++)
		p[i]=i;
	return true;
}

int Find(int x)            //找到根节点
{
	int r,i,j;

	r=x;
	while(r!=p[r]) r=p[r];      //路径压缩准备,找到根节点

	i=x;
	while(i!=p[i])
	{
		j=p[i];
		p[i]=r;
		i=j;
	}
	return i;                 //返回根节点
}

bool Merge(int x,int y)      //返回是否需要合并
{
	int tx,ty;

	tx=Find(x);
	ty=Find(y);

	if(tx==ty) return false;
	p[tx]=ty;
	return true;
}

int main()  
{ 
	int T,C,i,j,k,cnt;
	int tx,ty;
	double dis,sum;

	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&C);
		k=0;
		for(i=1;i<=C;i++)
		{
			scanf("%d%d",&point[i].x,&point[i].y);
			for(j=1;j<i;j++)
			{
				dis=Distance(point[i],point[j]);
				if(dis>=10 && dis<=1000)              //计算满足要求的边
				{
					edge[k].a=i;
					edge[k].b=j;
					edge[k++].v=dis;
				}
			}
		}
		Init(C);
		sort(edge,edge+k);
		cnt=C-1;
		sum=0;
		for(i=0;i<k;i++)
		{
			tx=Find(edge[i].a);
			ty=Find(edge[i].b);
			if(tx!=ty)                 //增加一条路,知道增加完C-1条
			{
				Merge(tx,ty);
				sum+=edge[i].v;
				cnt--;
				if(cnt==0) break;
			}
		}
		if(!cnt)                         //cnt不为0就不能修C-1条路
			printf("%.1lf\n",sum*100);
		else puts("oh!");
	}
    return 0;  
}


HDU ACM : 1875 畅通工程再续->最小生成树(并查集)

标签:acm   c++   并查集   算法   编程   

原文地址:http://blog.csdn.net/a809146548/article/details/44277567

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