
题目分析:
- 预处理出村庄间的高度差
g
[
i
]
[
j
]
g[i][j]
g[i][j]和距离
f
[
i
]
[
j
]
f[i][j]
f[i][j]
- 简化问题:有
n
n
n个点,
m
m
m条边,边有两个属性:
成
本
a
,
长
度
b
成本a,长度b
成本a,长度b,求
在构成一棵树的情况下
m
a
x
(
∑
a
[
i
]
∑
b
[
i
]
)
max(\frac{\sum{a[i]}}{\sum{b[i]}})
max(∑b[i]∑a[i])
- 设答案为
a
n
s
ans
ans,则有
∑
(
a
[
i
]
−
b
[
i
]
∗
a
n
s
)
<
=
0
\sum{(a[i]-b[i]*ans)}<=0
∑(a[i]−b[i]∗ans)<=0
- 二分
a
n
s
ans
ans,用
p
r
i
m
prim
prim来判断
Code:
#include <bits/stdc++.h>
using namespace std;
#define re register
#define maxn 1010
#define eps 1e-6
int n,g[maxn][maxn];
double f[maxn][maxn],d[maxn];
bool vis[maxn];
struct node {
int x,y,z;
}e[maxn];
inline void init_() {
freopen("a.txt","r",stdin);
}
inline int read_() {
int x=0,f=1;
char c=getchar();
while(c<'0'||c>'9') {
if(c=='-') f=-1;
c=getchar();
}
while(c>='0'&&c<='9') {
x=(x<<1)+(x<<3)+c-'0';
c=getchar();
}
return x*f;
}
inline void clean_() {
}
inline double dis_(double ax,double ay,double bx,double by) {
return sqrt( (ax-bx) * (ax-bx) + (ay-by) * (ay-by) );
}
inline bool pd_(double x) {
memset(vis,false,sizeof(vis));
vis[1]=true;d[1]=0;
for(re int i=2;i<=n;++i) {
d[i]= (double) ( (double) g[1][i]) - f[1][i]*x;
}
double sum=0,mind;
int u=-1;
for(re int i=2;i<=n;++i) {
mind=1e7;
for(re int k=1;k<=n;++k) {
if(!vis[k]&&d[k]<mind) {
mind=d[k];
u=k;
}
}
if(u==-1) break;
vis[u]=true;sum+=mind;
for(re int j=1;j<=n;++j) {
if(!vis[j]) d[j]=min(d[j],( (double) g[u][j])-f[u][j]*x);
}
}
if(sum>=0) return true;
else return false;
}
void readda_() {
while(scanf("%d",&n)!=EOF) {
if(!n) return;
clean_();
for(re int i=1;i<=n;++i) {
e[i].x=read_();e[i].y=read_();e[i].z=read_();
}
for(int i=1;i<=n;++i) {
for(int j=i+1;j<=n;++j) {
f[i][j]=f[j][i]=dis_( (double) e[i].x, (double) e[i].y, (double) e[j].x, (double) e[j].y);
g[i][j]=g[j][i]=abs(e[i].z-e[j].z);
}
}
double l=0,r=100,ans,mid;
while(r-l>eps) {
mid=(l+r)/2;
if(pd_(mid)) {
ans=mid;
l=mid;
}
else r=mid;
}
printf("%.3lf\n",ans);
}
}
int main() {
init_();
readda_();
return 0;
}