题意:
秦朝有n个城市,需要修路让每个城市都互相连通,现在可以免费修一条路,秦始皇希望他除了这条免费修的路外所需修的路的总和B最短,同时这条免费的路连接的人口之和A尽可能大,求最大的A/B是多少,城市之间的长度为欧几里得距离
思路:
这题是一个典型的最小生成树的题目。首先应该先求出最小生成树,其权值之和为W,然后再根据MST的回路性质,算出每一条路径对应的最大边权值,再进行遍历,求出最大的A/B即可
代码有参考这里
AC代码:
#include <stdio.h> #include <string.h> #include <math.h> #include <queue> #include <map> #include <vector> #include <algorithm> #include <bits/stdc++.h> #include <iostream> using namespace std; #define inf 0x3f3f3f3f typedef long long ll; const int maxn=1010; struct Edge { int a,b; double d; bool operator < (const Edge& rhs) const { return d < rhs.d; } }; int x[maxn]; int y[maxn]; int p[maxn]; int n; Edge e[maxn*maxn]; //G是与该节点相连的节点的编号,C是相应的cost vector<int> G[maxn]; vector<double> C[maxn]; int par[maxn]; void init(){ for(int i=0;i<n;i++){ par[i]=i; G[i].clear(); C[i].clear(); } } //int find(int x){return x==find(x)?x:par[x]=find(par[x]);} int find(int x) { if(x!=par[x]) par[x] = find(par[x]); return par[x]; } bool unite(int x,int y){ x=find(x); y=find(y); if(x==y){ return false; }else{ par[x]=y; return true; } } double mst(){ int cnt=0; for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ e[cnt].a=i; e[cnt].b=j; e[cnt].d=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); cnt++; } } // cout<<"ss"<<endl; sort(e,e+cnt); init(); for(int i=0; i<n; i++) { par[i] = i; G[i].clear(); C[i].clear(); } double ans=0; int cnt2=0; // cout<<"aa"<<endl; for(int i=0;i<cnt;i++){ if(unite(e[i].a,e[i].b)){ G[e[i].a].push_back(e[i].b); C[e[i].a].push_back(e[i].d); G[e[i].b].push_back(e[i].a); C[e[i].b].push_back(e[i].d); ans+=e[i].d; cnt2++; if(cnt2==n-1) break; } } // cout<<ans<<endl; return ans; } double costs[maxn][maxn]; vector<int> nodes; //u是现在在搜索的节点,fa是u的父节点(从哪来),facost是之前来的那条路的cost void dfs(int u, int fa, double facost) { for(int i = 0; i < nodes.size(); i++) { int x = nodes[i]; costs[u][x] = costs[x][u] = max(costs[x][fa], facost); } nodes.push_back(u); for(int i = 0; i < G[u].size(); i++) { int v = G[u][i]; if(v != fa) dfs(v, u, C[u][i]); } } int main(){ int t; scanf("%d",&t); while(t--){ scanf("%d",&n); for(int i=0;i<n;i++){ scanf("%d%d%d",&x[i],&y[i],&p[i]); } // cout<<"hh"<<endl; double total=mst(); memset(costs,0,sizeof(costs)); nodes.clear(); dfs(0, -1, 0); double ans = -1; for(int i=0; i<n; i++) { for(int j=i+1; j<n; j++) { ans = max(ans,(p[i]+p[j])/(total-costs[i][j])); } } printf("%.2lf ",ans); } return 0; }