0915-分数规划(最优比率生成树)-POJ 2728

版权声明:虽然我只是个小蒟蒻但转载也请注明出处哦 https://blog.csdn.net/weixin_42557561/article/details/82708770

【小知识】

(一不小心被自己秀到了……居然忘记了Prim算法)

结论:Prim算法主要用于稠密图,尤其是完全图的最小生成树的求解

大概就是对于一个完全图(每两个点都有一条边),其边数肯定超级多,那么使用Kruskal算法(按边枚举)显然不现实,我们就使用Prim,枚举顶点

传送门

分析

这就是相当于任意两个点之间有一条连线,这条边上有其对应的成本(两点高度之差)和长度(欧几里得距离),最后 要求 所有的点连通,并且选出来的这些边的总成本比上其总长度,值最小

和之前那道01分数规划比较相似(就是因为相似,我才傻逼的把二分上界仍然定义为1……omg,都不动脑壳思考一下),但不同的是这次我们要求的是最小值,令 min r = \frac{\sum cost[i]}{\sum len[i]},(r 即最后所求的最优解,为了方便我们就用a(x)来代表此时的分子,b(x)代表分母,再定义一个函数 g(r)=min\left \{ a(x)-r*b(x) \right \},然后胡搞证明一下这个的单调性,就可以二分来做啦,

每次二分出来一个 r 就来验证一下,将每一条边的权值都重新更新,然后用Prim求最小生成树,将最后的和与0做比较,确定二分上下界的调整

代码

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#define N 2009
#define eps 1e-10
#define in read()
#define inf 1e9 
using namespace std;
inline int read(){
	char ch;int res=0;
	while((ch=getchar())<'0'||ch>'9');
	while(ch>='0'&&ch<='9'){
		res=(res<<3)+(res<<1)+ch-'0';
		ch=getchar();
	} 
	return res;
}
int n,x[N],y[N],z[N];
double dis[N][N],cost[N][N],w[N];
bool v[N];
bool check(double r){
	for(int i=1;i<=n;++i)	w[i]=cost[i][1]-r*dis[i][1];//更新
	memset(v,0,sizeof(v));
	v[1]=1;
	double res=0;
	for(int i=2;i<=n;++i){
		double minn=1e9;
		int pos; 
		for(int j=1;j<=n;++j)	if(!v[j]&&w[j]<minn) minn=w[j],pos=j;
		v[pos]=1;
		res+=minn;
		for(int j=1;j<=n;++j){
			if(v[j]) continue;
			if(w[j]>cost[pos][j]-r*dis[pos][j])
				w[j]=cost[pos][j]-r*dis[pos][j];
		}
	}
	return res>0.0;
}
int main(){
	while((scanf("%d",&n))!=EOF){
		if(n==0) break;
		int i,j;
		for(i=1;i<=n;++i){	x[i]=in;y[i]=in;z[i]=in;  }
		for(i=1;i<=n;++i)
			for(j=1;j<=n;++j){
				dis[i][j]=dis[j][i]=(double)sqrt((double)(x[i]-x[j])*(x[i]-x[j])+(double)(y[i]-y[j])*(y[i]-y[j]));
				cost[i][j]=cost[j][i]=(double)abs(z[i]-z[j]);
			}
		double l=0,r=100;//开大一点也可以的
		while(r-l>1e-10){
			double mid=(l+r)/2.0;
			if(check(mid)) l=mid;
			else r=mid;
		}
		printf("%.3f\n",l);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_42557561/article/details/82708770
今日推荐