您的位置:首页 > 其它

UVa 10397 - Connect the Campus

2014-03-22 01:44 337 查看
题目:给你一些建筑,以及他们之间的一些电缆,问把他们都连起来还需要多少电缆。

分析:最小生成树。将已有的电缆长度定义为0,直接进行最小生成树算法即可。

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#include <cmath>

using namespace std;

typedef struct p_node
{
	int x,y;
}pnode;
pnode p[755];

double dist( int a, int b )
{
	return sqrt(0.0+(p[a].x-p[b].x)*(p[a].x-p[b].x)+(p[a].y-p[b].y)*(p[a].y-p[b].y));
}

typedef struct d_node
{
	int 	point1;
	int 	point2;
	double 	weight;
}enode;
enode edge[565000];

//union_set
int sets[755];
int rank[755];

void set_inital( int a, int b )
{
	for ( int i = a ; i <= b ; ++ i ) {
		rank[i] = 0;
		sets[i] = i;
	}
}

int  set_find( int a )
{
	if ( a != sets[a] )
		sets[a] = set_find( sets[a] );
	return sets[a];
}

void set_union( int a, int b )
{
	if ( rank[a] < rank[b] )
		sets[a] = b;
	else {
		if ( rank[a] == rank[b] )
			rank[a] ++;
		sets[b] = a;
	}
}
//end_union_set

int cmp_e( enode a, enode b )
{
	return a.weight < b.weight;
}

double kruskal( int n, int r )
{
	set_inital( 1, n );
	sort( edge, edge+r, cmp_e );
	
	double sum = 0;
	for ( int i = 0 ; i < r ; ++ i ) {
		int A = set_find( edge[i].point1 );
		int B = set_find( edge[i].point2 );
		if ( A != B ) {
			set_union( A, B );
			sum += edge[i].weight;
		}
	}
	return sum;
}

int smap[755][755];

int main()
{
	int n,m,a,b;
	while ( scanf("%d",&n) != EOF ) {
		memset( smap, 0, sizeof(smap) );
		for ( int i = 1 ; i <= n ; ++ i )
			scanf("%d%d",&p[i].x,&p[i].y);
		scanf("%d",&m);
		for ( int i = 1 ; i <= m ; ++ i ) {
			scanf("%d%d",&a,&b);
			smap[a][b] = smap[b][a] = 1;
		}
		int r = 0;
		for ( int i = 1 ; i <= n ; ++ i )
		for ( int j = 1 ; j < i ; ++ j ) {
			edge[r].point1 = i;
			edge[r].point2 = j;
			edge[r].weight = (!smap[i][j])*dist( i, j );
			r ++;
		}
		
		printf("%.2lf\n",kruskal( n, r ));
	}
	return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: