# NOJ 2015年陕西省程序设计竞赛网络预赛(正式赛)(落后的小岛-最小生成树-并查集迭代路径优化与不优化对比)[Hobo]

G - 落后的小岛

Time Limit: 3000 ms        Memory Limit: 10240 KB
Submit

Description

在某片海域分布着n座小岛,每个小岛的位置用一对整数(x, y)表示。但是小岛上的条件十分落后,人们只能划船到其他岛,这非常不方便。有一天,智慧与勇气并存的温温来到了这片海域,她决定帮助居民在小岛之间建立通讯网络。在现有的条件下,通讯工具可以是无线电收发机,也可以是卫星设备。温温可以给所有的小岛都配上无线电收发机,但是收发机的成本与小岛之间距离成正比,为了简化问题,我们认为两岛之间的距离即为装配无线电收发机的花费。另外一种方案是给任意两个小岛之间装上卫星设备(有人赞助,所以没有任何花费),这样无论两个小岛相距多远,都可以进行通讯。但是令人非常郁闷的是,卫星设备的数量十分有限。请你快点帮温温想想办法,怎么样合理分配卫星设备和架设无线电网络,才能保证花费最小,并且使任意两个小岛之间都可以实现直接或间接的通讯。

Input

输入包含多组测试数据。

第一行输入小岛的总数n,和卫星设备的个数k,( 1 ≤ n,k ≤ 200 )。

接下来n行分别输入各个小岛的坐标值(x,y),(0 ≤ x, y ≤ 1000)。

当n=0且k=0时,输入结束。

 

Output

第一行输出测试数据的编号。

第二行输出最小的花费,结果保留两位小数。

每组数据的输出之后有一个空行

 

Sample Input

4 1
1 1
2 1
3 2
5 2
4 2
1 1
2 1
3 2
5 2
0 0

Sample Output

Case #1:
The minimal cost is: 4.41

Case #2:
The minimal cost is: 2.41

Hint

-

cjq开的题,因为 define *号 的问题 RE 了
因为 成员函数 没写返回值 CE了
因为(cin>>n>>k && n && k ) WA 了
又因为判‘重点' (没必要) WA了
然后迭代路径压缩玩TLE 了

获得成就【同一场比赛分数最高&&罚时最多】


#include <bits/stdc++.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>

#define LL long long
#define ULL unsigned long long
#define LD long double

#define Rep(x,y,i) for (int i=x;i<y;i++) //[x,y)
#define RepD(x,y,i) for (int i=x;i>y;i--) //(y,x]
#define Mem(X) memset(X,0,sizeof(X));
#define Pr(X) cout<<#X<<"="<<X<<" ";
#define PrL(X) cout<<#X<<" = "<<X<<endl;
#define PrLL cout<<endl;

using namespace std;

const double EPS=1e-10;



struct Point
{
	int x;
	int y;
	Point (int a,int b) { x=a; y=b; }
	bool operator == (const Point& a) { return (x==a.x && y==a.y); }
};

#define MAXN 200+100
int U[50000],V[50000],Q[50000];
double W[50000];
int P[MAXN*MAXN];
int k, n;
int B;
double ANS;

int find(int x)
{
	if (P[x]==x) return x;
	else return P[x]=find(P[x]); 
}
void mergeg(int x,int y)
{
	int a=find(P[x]),b=find(P[y]);
	if (a!=b) P[a]=b; 
} 

bool cmp(const int i,const int j) {return W[i]<W[j];}

vector<Point> q;

struct Graph
{
	
	
	double S[MAXN][MAXN];
	
	void add(int x, int y) { q.push_back(Point(x,y)); }
	
	void generate()
	{

		Mem(S);
		Mem(U);
		Mem(V);
		Mem(W);
		Mem(Q);
		Rep(0,n,i) P[i]=i;
		
		int M=0;
		for (int i=0;i<n;i++)
			for (int j=0;j<i;j++)
			{
				U[M]=i;
				V[M]=j;
				double t1=q[i].x-q[j].x;
				double t2=q[i].y-q[j].y;
				W[M]=sqrt(t1*t1+t2*t2);
				Q[M]=M;
				M++;
			}
		sort(Q,Q+M,cmp);
		ANS=0;
		B=0;
		for (int i=0;i<M;i++)
		{
			if (B>=(n-k)) {break;}
			int E=Q[i];
			int X=find(U[E]);
			int Y=find(V[E]);
			if (X!=Y) 
			{
				ANS+=W[E];
				mergeg(X,Y);
				B++;
			}
			if (B>=(n-k)) {break;}
		}
		printf("%.2lf\n",ANS);
	}
	
	
	
}a;

int main()
{
//	freopen("G.in","r",stdin);
	int ccase=1;
	while (scanf("%d%d",&n,&k)==2)
	{
		if (n==0&&k==0) return 0;
		q.clear();q.reserve(300);
		cout<<"Case #"<<ccase<<":\n";
		cout<<"The minimal cost is: ";
		Rep(0,n,i)
		{
			int tt1,tt2;
			scanf("%d%d",&tt1,&tt2);
			a.add(tt1,tt2);
		}
		a.generate();
		ccase++;	
		cout<<endl;
	}
	
	return 0;
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值