POJ 2349

再次因为浮点数g++, c++编译器的问题WA,中间还因为reset没有改过来编译器无脑再WA了一次

这道题很适合Kruskal这种将最开始的联通森林,一点点聚合到一起成为一棵联通的最小生成树的想法,只不过,具体到这道题,是要将原先的p个森林,聚合成为s个森林,所以实现就非常简单了

#include <iostream>
#include <algorithm>
#include <queue>
#include <string>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <string>
#include <stack>
#include <map>
#include <set>
using namespace std;

const int maxp= 505;

struct Edge
{
	int u, v;
	double d;
	Edge(int _u= 0, int _v= 0, double _d= 0) : u(_u), v(_v), d(_d) {}
	bool operator < (const Edge &rhs) const
	{
		return d< rhs.d;
	}
}G[(maxp*maxp)>>1];
int x[maxp], y[maxp];
int fa[maxp], rk[maxp];

int Find(int x)
{
	if (x== fa[x]){
		return x;
	}

	return fa[x]= Find(fa[x]);
}
void Union(int x, int y)
{
	x= Find(x);
	y= Find(y);
	if (x== y){
		return;
	}

	if (rk[x]> rk[y]){
		fa[y]= x;
		rk[x]+= rk[y];	
	}
	else{
		fa[x]= y;
		rk[y]+= rk[x];
	}
}
inline double Dist(const int i, const int j)
{
	return sqrt(double((x[i]-x[j])*(x[i]-x[j]))+double((y[i]-y[j])*(y[i]-y[j])));
}
double Kruskal(const int n, const int m, const int s)
{
	sort(G, G+m);
	double ans= 0;
	int cnt= n;
	for (int i= 0; i< m; ++i){
		int u= G[i].u, v= G[i].v;
		int f_u= Find(u), f_v= Find(v);
		if (f_u== f_v){
			continue;
		}

		ans= max(ans, G[i].d);
		if (s== --cnt){
			break;
		}
		Union(u, v);
	}

	return s== cnt ? ans : -1;
}
int main()
{
	int kase;
	int s, p, m;
	scanf("%d", &kase);
	while (kase--){
		m= 0;
		scanf("%d %d", &s, &p);
		for (int i= 0; i< p; ++i){
			scanf("%d %d", x+i, y+i);
			fa[i]= i;
			rk[i]= 1;
		}
		for (int i= 0; i< p; ++i){
			for (int j= i+1; j< p; ++j){
				G[m++]= Edge(i, j, Dist(i, j));
			}
		}
		printf("%.2lf\n", Kruskal(p, m, s));
	}

	return 0;
}
posted @ 2021-04-13 21:56  IdiotNe  阅读(39)  评论(0编辑  收藏  举报