prim + 邻接矩阵储存两点间最大距离,然后枚举即可。
#include<iostream> #include<string> #include<cstdio> #include<set> #include<map> #include<stack> #include<list> #include<vector> #include<queue> #include<algorithm> #include<cstring> #include<cmath> #include<fstream> using namespace std; typedef long long ll; const int maxn = 1010,INF = 0x3f3f3f3f; int fa[maxn],n; vector<int> son[maxn]; int x[maxn],y[maxn],pop[maxn]; double maxr[maxn][maxn];//最小生成树中两点间的最大边 double sum,ans; double e[maxn][maxn]; struct Edge{ int to,from; double val; bool operator < (const Edge &x) const{ return val < x.val; } }; int getfa(int x){ if (fa[x] == x) return x; else return fa[x] = getfa(fa[x]); } inline double pf(double x){ return x * x; } inline double getdis(int u,int v){ return sqrt(pf(x[u] - x[v]) + pf(y[u] - y[v])); } void buildEdge(){ for(int i = 1;i <= n;++i) for(int j = i+1;j <= n;++j){ double dis = getdis(i, j); e[i][j] = e[j][i] = dis; } } void prim() { bool vis[maxn] = {}; double dist[maxn] = {}; for(int i = 1;i <= n;++i) { dist[i] = INF; } vector<int> v; int now = 1; int pre[maxn] = {}; sum = 0; vis[1] = true; dist[1] = 0; v.push_back(1); for(int i = 1;i < n;++i) { for(int j = 1;j <= n;++j) { if(!vis[j] && e[now][j] < dist[j]){ pre[j] = now; dist[j] = e[now][j]; } } double mi = INF; int k = i; for(int j = 1;j <= n;++j) { if(!vis[j] && dist[j] < mi) { mi = dist[j]; k = j; } } sum += dist[k]; now = k; vis[k] = 1; for(int j = 0;j < v.size();++j) { maxr[v[j]][k] = maxr[k][v[j]] = max(maxr[v[j]][pre[k]],dist[k]); } v.push_back(k); } } void solve(){ double ans = 0; for(int i = 1;i <= n;++i) for(int j = i + 1;j <= n;++j){ double A = pop[i] + pop[j]; double B = sum - maxr[i][j]; ans = max(ans,A/B); } printf("%.2f\n",ans); } void init(){ cin >> n; for(int i = 1;i <= n;++i){ cin >> x[i] >> y[i] >> pop[i]; } memset(maxr,0,sizeof maxr); for(int i = 1;i <= n;++i) { for(int j = i + 1;j <= n;++j) e[i][j] = e[j][i] = INF; } buildEdge(); prim(); solve(); } int main(){ int t; cin >> t; while(t--){ init(); } }