您的位置:首页 > 其它

Qin Shi Huang's National Road System - HDU 4081 - 次小生成树

2017-07-02 22:57 399 查看

Qin Shi Huang’s National Road System - HDU 4081 - 次小生成树

题意

  
T
组样例,每组样例
n
个点,每个点给出
x y v
,对应这个点的横纵坐标和权,让你求出
(点A的权+点B的权)/(最小生成树的权-点AB所在那条路的权)
的最大值。

思路

  对于某两个点A和B,两个点的权值之和是固定的,最小生成树的权通过计算之后也是已知的。也就是说对于上述表达式,对于每两个点来说分子是固定的,分母的最小生成树权也是固定的。所以很容易得到:点AB所在的那条路的权值越大,表达式的比值就越大,于是就转化成为了一个次小生成树的问题。

代码

#include <algorithm>
#include <cstdio>
#include <cmath>
#include <cstring>
#define memset(a,b) memset(a,b,sizeof(a))
#define il inline
using namespace std;
#define maxn 1007
const double INF = 0x3f3f3f3f;
int n, pre[maxn], index;
double mp[maxn][maxn], dis[maxn], maxdis[maxn][maxn], result, ans, minn;
bool vis[maxn];
struct {
double x,y;
int v;
}point[maxn];
il double getdis(double x1, double y1, double x2, double y2) {
double x_ = x1 - x2, y_ = y1 - y2;
return sqrt(x_ * x_ + y_ * y_);
}
void prim() {
memset(maxdis,0);
memset(vis,false);
vis[1] = true;
ans = 0;
for(int i=2 ; i<=n ; i++)
dis[i] = mp[1][i],pre[i] = 1;
for(int k=1 ; k<n ; k++) {
index = -1, minn = INF;
for(int i=2 ; i<=n ; i++) {
if(!vis[i] && dis[i] < minn) {
minn = dis[i];
index = i;
}
}
ans += dis[index];
vis[index] = true;
for(int i=1 ; i<=n ; i++) {
if(vis[i] && i!=index) maxdis[i][index] = maxdis[index][i] = max(maxdis[i][pre[index]], dis[index]);
else if(!vis[i] && mp[index][i] < dis[i]) {
dis[i] = mp[index][i];
pre[i] = index;
}
}
}
}
int main() {
int t;
scanf("%d",&t);
while(t--) {
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%lf%lf%d", &(point + i)->x, &(point + i)->y, &(point + i)->v);
for (int i = 1; i <= n; i++) {
mp[i][i] = 0;
for (int j = i + 1; j <= n; j++)
mp[i][j] = mp[j][i] = getdis(point[i].x, point[i].y, point[j].x, point[j].y);
}
prim();
result = -1;
for (int i = 1; i <= n; i++)
for (int j = i + 1; j <= n; j++)
result = max(result, (point[i].v + point[j].v) / (ans - maxdis[i][j]));
printf("%.2f\n", result);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息