UVa10397 Connect the Campus

        题意:平面坐标系中有N个点,其中部分点之间已经连通。在这个图上补充边,使整个图连通,且边的总长度最小。

        思路:类似于最小生成树,Prim算法一开始没想出来思路,就用Kruskal写了。已经连接的点并到一个集合里,求剩下部分的最小生成树。。。话说用这种方法效率有点低,占内存还大,但是对于这个数据量还是能过的。


#include <iostream>
#include <stdio.h>
#include <cmath>
#include <algorithm>
#include <iomanip>
#include <cstdlib>
#include <string>
#include <memory.h>
#include <vector>
#include <queue>
#include <stack>
#include <ctype.h>

using namespace std;


struct point{
	int x;
	int y;
};
point pt[800];

int parent[800];
int get_p(int i){
	if(parent[i]!=i){
		parent[i]=get_p(parent[i]);
	}
	return parent[i];
}
void uni(int a,int b){//合并
	if(get_p(a)!=get_p(b)){
		parent[get_p(b)]=get_p(a);
	}
}

double dist(point a,point b){//两点距离
	return sqrt((double)(a.x-b.x)*(a.x-b.x)+(double)(a.y-b.y)*(a.y-b.y));
}
struct edge{
	int u;
	int v;
	double len;
};
edge E[562510];
bool cmp(edge a,edge b){
	return a.len<b.len;
}

int main(){
	
	int n;
	
	while(cin>>n){
		//init
		for(int i=0;i<800;i++){
			parent[i]=i;
		}
		//
		for(int i=1;i<=n;i++){
			scanf("%d%d",&pt[i].x,&pt[i].y);
		}
		//calc all distances
		int k=0;
		for(int i=2;i<=n;i++){
			for(int j=1;j<i;j++){
				E[k].len=dist(pt[i],pt[j]);
				E[k].u=i;
				E[k++].v=j;
			}
		}
		sort(E,E+k,cmp);
		
		int m;
		cin>>m;
		for(int i=1;i<=m;i++){
			int u,v;
			scanf("%d%d",&u,&v);
			uni(u,v);//已经存在边的点并起来
		}
		
		double ans=0.0;
		for(int i=0;i<k;i++){//这里写坑了,连完以后没有跳出
			if(get_p(E[i].u)!=get_p(E[i].v)){
				ans+=E[i].len;
				uni(E[i].u,E[i].v);
			}
		}
		printf("%.2lf\n",ans);
	}
	return 0;
}



你可能感兴趣的:(kruskal,uva)