POJ 2728 Desert King

最优比例生成树。

首先是个完全图,所以Kruskal算法不好用,于是写Prim。

第一次写Prim算法,表示不知道nlogm怎么优化出来的,感觉我怎么想都是mlogm。

于是果断弃疗用邻接矩阵。

由于懒得学Dinkelbach算法,于是就用二分来水一水。

不妨设F(L)=sigma(h[i]-l[i]*L)*x[i],假如F(L)的最小值大于0,即无论x[i]怎么取(要按照基本法来),都不能达到L,那么只能说明答案比L大,否则答案比L小。

顺便吐槽一下POJ上G++用lf会WA,用f才能过- -

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
const int N=1000+5;
const double inf=100000000.0;
int n;
bool vis[N];
double x[N],y[N],h[N];
double d[N],dis[N][N],cost[N][N];
double sqr(double x){return x*x;}
double dist(int i,int j){
	return sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
}
bool check(double x){
	double sum=0.0;
	memset(vis,0,sizeof(vis));
	vis[1]=true;
	for(int i=2;i<=n;i++)d[i]=cost[1][i]-dis[1][i]*x;
	int k;
	for(int i=2;i<=n;i++){
		double mincost=inf;
		for(int j=2;j<=n;j++)
		if(!vis[j]&&d[j]<mincost)mincost=d[j],k=j;
		vis[k]=true;
		sum+=mincost;
		for(int j=2;j<=n;j++)
		if(!vis[j]&&cost[k][j]-dis[k][j]*x<d[j])
		d[j]=cost[k][j]-dis[k][j]*x;
	}
	return sum>=0;
}
int main(){
	while(scanf("%d",&n)&&n){
		for(int i=1;i<=n;i++)
		scanf("%lf%lf%lf",&x[i],&y[i],&h[i]);
		for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++){
			dis[i][j]=dis[j][i]=dist(i,j);
			cost[i][j]=cost[j][i]=abs(h[i]-h[j]);
		}
		double l=0,r=100;
		while(r-l>(1e-6)){
			double mid=(l+r)/2;
			if(check(mid))l=mid;
			else r=mid;
		}
		printf("%.3f\n",l);
	}
	return 0;
}
	


你可能感兴趣的:(POJ 2728 Desert King)