poj 2728 最优比率树(最小生成树问题)

好蛋疼啊,由于double 不能用memset,害的我调了一个多小时才发现。由于用二分搜索,时间有点大

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#define maxn 1005
using namespace std;

const int INF = 0x3f3f3f;

struct node{
	int x,y,z;
}Node[maxn];
double d[maxn];
double G[maxn][maxn];
double cost[maxn][maxn];
double benefit[maxn][maxn]; 
int  n;
double mid,ans;

void calculate(int i,int j){
	cost[i][j] = cost[j][i] = abs(Node[i].z - Node[j].z);
	int x1=Node[i].x, y1=Node[i].y;
	int x2=Node[j].x, y2=Node[j].y;
	benefit[i][j] = benefit[j][i] = sqrt(1.0*(x1-x2)*(x1-x2) + 1.0*(y1-y2)*(y1-y2));
}

void makemap(){
	for(int i=1;i<=n;i++)
	 for(int j=i+1;j<=n;j++){
  		G[i][j] = G[j][i] = cost[i][j] - mid * benefit[i][j]; 
  	}
  	
  	return;
}
void prim(){
	bool vis[maxn];
	double mindist;
	double lowdist[maxn];
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++) lowdist[i] = INF;
	int point;
	ans = 0.0;
	int s=1;
	int num=1;
	while(true){
		if(num == n) break;
		vis[s] = true;
		mindist = INF;
		for(int i=1;i<=n;i++){
			if(!vis[i] && lowdist[i] > G[s][i]){
   				lowdist[i] = G[s][i];
			}
			if(!vis[i] && lowdist[i] < mindist){
				mindist = lowdist[i];  
				point = i;
			}
		} 
		s = point;
		ans += mindist;  
		num++;
	}
	return;
}
int main()
{
	//if(freopen("input.txt","r",stdin)== NULL)  {printf("Error\n"); exit(0);}

	while(cin>>n && n){
		for(int i=1;i<=n;i++){
			cin>>Node[i].x>>Node[i].y>>Node[i].z;
		}
		for(int i=1;i<=n;i++)
		     for(int j=i+1;j<=n;j++){
  			    calculate(i,j);
  		     }
		double R=10000000,L=0.0;
		while( (R-L)>1e-6 ){
		   mid = (R+L)/2;	
	       for(int i=1;i<=n;i++)
	          for(int j=1;j<=n;j++){
          		G[i][j] = INF;
          	}
		   makemap();
  		   prim();
		   if(ans >= 0)  L = mid; 
		   else          R = mid; 
		   
		}
		printf("%.3lf\n",L);
	}
	return 0;
}

  还是迭代好上面的用时2500多MS,而这个只要297MS,空间复杂度是降不下来了。

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <iostream>
#define maxn 1005
using namespace std;

const int INF = 0x3f3f3f;

struct node{
	int x,y,z;
}Node[maxn];
double d[maxn];
double G[maxn][maxn];
double cost[maxn][maxn];
double benefit[maxn][maxn]; 
int  n;
double mid,ans;

void calculate(int i,int j){
	cost[i][j] = cost[j][i] = abs(Node[i].z - Node[j].z);
	int x1=Node[i].x, y1=Node[i].y;
	int x2=Node[j].x, y2=Node[j].y;
	benefit[i][j] = benefit[j][i] = sqrt(1.0*(x1-x2)*(x1-x2) + 1.0*(y1-y2)*(y1-y2));
}

void makemap(){
	for(int i=1;i<=n;i++)
	 for(int j=i+1;j<=n;j++){
  		G[i][j] = G[j][i] = cost[i][j] - mid * benefit[i][j]; 
  	}
  	
  	return;
}
void prim(){
	bool vis[maxn];
	double mindist;
	struct low{
		double lowdist;
		int s;
	}L[maxn]; 
	memset(vis,0,sizeof(vis));
	for(int i=1;i<=n;i++) L[i].lowdist = INF;
	int point;
	ans = 0.0;
	int s=1;
	int num=1;
	double suma = 0.0,sumb = 0.0;
	while(true){
		if(num == n) break;
		vis[s] = true;
		mindist = INF;
		for(int i=1;i<=n;i++){
			if(!vis[i] && L[i].lowdist > G[s][i]){
   				L[i].lowdist = G[s][i];
   				L[i].s = s;
			}
			if(!vis[i] && L[i].lowdist < mindist){
				mindist = L[i].lowdist;  
				point = i;
			}
		} 
		int a = L[point].s; 
		suma += cost[a][point];
		sumb += benefit[a][point];
		
		s = point;
		num++;
	}
	ans = suma/sumb;
	return;
}
int main()
{
	//if(freopen("input.txt","r",stdin)== NULL)  {printf("Error\n"); exit(0);}

	while(cin>>n && n){
		for(int i=1;i<=n;i++){
			cin>>Node[i].x>>Node[i].y>>Node[i].z;
		}
		for(int i=1;i<=n;i++)
		     for(int j=i+1;j<=n;j++){
  			    calculate(i,j);
  		     }
  		mid = 0.5;     
		while( true){
		   for(int i=1;i<=n;i++)
	          for(int j=1;j<=n;j++){
          		G[i][j] = INF;
           }
		   makemap();
  		   prim();
  		   
		   if(abs(ans -mid) < 1e-6)  break;
   		   else           mid = ans; 
		}
		printf("%.3lf\n",ans);
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/acmdeweilai/p/3093267.html