机试算法讲解: 第35题 欧拉回路之一笔画

/*
问题:平面有若干点,用线段将点连接,使任意两点通过一些列线段相连,给出所有点的坐标,求一种连接方法使所有线段的长度和最小,求该长度和
本质:点为图上的节点,节点之间的线段为边,权值为其长度,求最小生成树之前需要建立图
关键:
1 需要建立点结构体,并且计算任意两点之间的距离,赋予边的结构体,再将边排序,求出最小生成树
2 输入的类型必须也是浮点类型,接受取值的也是浮点类型。printf("%d %d\n",&nodeArr[i]._dX,&nodeArr[i]._dY)必须改为printf("%f %f\n",&nodeArr[i]._dX,&nodeArr[i]._dY)
3 用sqrt()里面只能放一个计算好的值,不能在里面计算
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#define N 1000
int Tree[N];

typedef struct Edge
{
	int _iV1,_iV2;//一条边的顶点编号
	double _dWeight;//边上的权值
	bool operator <= (const Edge& edge)
	{
		return _dWeight < edge._dWeight;
	}
}Edge;

int partition(Edge* edgePtr,int low,int high)
{
	Edge ePos = edgePtr[low];
	while(low < high)
	{
		while(low < high && ePos <= edgePtr[high])
		{
			high--;
		}
		edgePtr[low] = edgePtr[high];
		while(low < high && edgePtr[low] <= ePos)
		{
			low++;
		}
		edgePtr[high] = edgePtr[low];
	}
	edgePtr[low] = ePos;
	return low;
}

void quickSort(Edge* edgePtr,int low,int high)
{
	if(low < high)
	{
		int iPos = partition(edgePtr,low,high);
		quickSort(edgePtr,low,iPos-1);
		quickSort(edgePtr,iPos+1,high);
	}
}

int findRoot(int x)
{
	if(-1==Tree[x])
	{
		return x;
	}
	else
	{
		int iRoot = findRoot(Tree[x]);
		Tree[x] = iRoot;
		return iRoot;
	}
}

typedef struct Node
{
	double _dX,_dY;//一个节点的横,纵坐标
	//获取两点之间的距离
	double getDistance(const Node& node)
	{
		double res =  (_dX-node._dX)*(_dX-node._dX) + (_dY-node._dY)*(_dY -node._dY);
		return sqrt(res);
	}
}Node;


int main(int argc,char* argv[])
{
	int iNum,i;
	while(EOF!=scanf("%d",&iNum))
	{
		//获取输入信息
		//double dX,dY;
		Edge edgeArr[1000];
		Node nodeArr[1000];
		//获取所有点信息
        for(i = 0 ; i < iNum ; i++)
		{
			scanf("%lf %lf",&nodeArr[i]._dX,&nodeArr[i]._dY);//易错,这里输入的类型和必须是%f
		}

		//建立边的信息
		int iSize = 0 ;
		for(i = 0 ; i < iNum ; i++)
		{
			for(int j = i + 1 ; j < iNum; j++)
			{
				//易错,edgeArr[iSize++]._iV1 = i;
				edgeArr[iSize]._iV1 = i;
				//edgeArr[iSize++]._iV2 = j;
				edgeArr[iSize]._iV2 = j;
				//获取两个结点之间的距离
				edgeArr[iSize]._dWeight = nodeArr[i].getDistance(nodeArr[j]);
				iSize++;
			}
		}
		//对边进行快速排序
		quickSort(edgeArr,0,iSize-1);

		//易错,对于边,设定每个边的父节点为根结点.这边错误,因为需要将n对顶点之间的每一个顶点的父节点的值设为-1
		//for(i = 0; i < iSize;i++)
		//iNum个顶点
		for(i = 0 ; i < iNum ; i++)
		{
			Tree[i] = -1;
		}

		//对于边,求最小生成树
		double dWeightSum = 0;
		for(i = 0 ; i < iSize ; i++)
		{
			int iRoot1 = findRoot(edgeArr[i]._iV1);
			int iRoot2 = findRoot(edgeArr[i]._iV2);
			if(iRoot1!=iRoot2)
			{
				Tree[iRoot1] = iRoot2;
				dWeightSum += edgeArr[i]._dWeight;
			}
		}
		printf("%.2f\n",dWeightSum);
	}
	system("pause");
	getchar();
	return 0;
}

你可能感兴趣的:(欧拉回路,一笔画,机试算法)