https://vjudge.net/problem/UVALive-5713
题意:
秦朝有n个城市,需要修建一些道路使得任意两个城市之间都可以连通。道士徐福声称他可以用法术修路,不花钱,也不用劳动力,但只能修一条路,因此需要慎重选择用法术修哪一条路。秦始皇不仅希望其他道路的总长度B尽量短(这样可以节省劳动力),还希望法术连接的两个城市的人口之和A尽量大,因此下令寻找一个使得A/B最大的方案。你的任务是找到这个方案。
任意两个城市之间都可以修路,长度为两个城市之间的欧几里德距离。
思路:
先计算出最小生成树,之后用法术修的路肯定在最小生成树当中,那么之后我们就可以枚举边u-v。
当然,需要预处理,像最小生成树一样,计算出u和v之间唯一路径上的最大权maxcost[u][v]。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstdio> 4 #include<cstring> 5 #include<string> 6 #include<vector> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 using namespace std; 11 typedef long long LL; 12 const int maxn=1000+5; 13 14 struct node 15 { 16 int u,v; 17 double dist; 18 bool operator < (const node& rhs) const 19 { 20 return dist<rhs.dist; 21 } 22 }edge[maxn*maxn]; 23 24 int n; 25 int cnt; 26 int p[maxn]; 27 int x[maxn],y[maxn]; 28 int num[maxn]; 29 vector<int> g[maxn]; //存储最小生成树中结点u的邻接结点 30 vector<double> c[maxn]; //c[u][i]表示结点u和和结点g[u][i]之间的边权 31 32 double maxcost[maxn][maxn]; //u,v两点之间的最大边权 33 vector<int> nodes; 34 35 int find(int x) 36 { 37 return x==p[x]?x:p[x]=find(p[x]); 38 } 39 40 double MST() 41 { 42 sort(edge,edge+cnt); 43 int tot_edge=0; 44 double tot_q=0; 45 for(int i=0;i<cnt;i++) 46 { 47 int x=edge[i].u, y=edge[i].v; 48 int u=find(x), v=find(y); 49 if(u!=v) 50 { 51 p[u]=v; 52 g[x].push_back(y); c[x].push_back(edge[i].dist); 53 g[y].push_back(x); c[y].push_back(edge[i].dist); 54 tot_q+=edge[i].dist; 55 if(++tot_edge==n-1) break; 56 } 57 } 58 return tot_q; 59 } 60 61 void dfs(int u,int fa,double cost) //无根树转有根树,计算出u,v两点之间路径的最大边权 62 { 63 for(int i=0;i<nodes.size();i++) 64 { 65 int x=nodes[i]; 66 maxcost[x][u]=maxcost[u][x]=max(maxcost[x][fa],cost); //更新之前的结点与新加入的结点之前的最大边权 67 } 68 nodes.push_back(u); 69 for(int i=0;i<g[u].size();i++) 70 { 71 int v=g[u][i]; 72 if(v!=fa) dfs(v,u,c[u][i]); 73 } 74 } 75 76 int main() 77 { 78 //freopen("D:\input.txt","r",stdin); 79 int T; 80 scanf("%d",&T); 81 while(T--) 82 { 83 cnt=0; 84 scanf("%d",&n); 85 for(int i=0;i<n;i++) {p[i]=i; g[i].clear(); c[i].clear();} 86 for(int i=0;i<n;i++) 87 { 88 scanf("%d%d%d",&x[i],&y[i],&num[i]); 89 for(int j=0;j<i;j++) 90 { 91 edge[cnt].u=j; 92 edge[cnt].v=i; 93 edge[cnt].dist=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j])); 94 cnt++; 95 } 96 } 97 double tot=MST(); 98 memset(maxcost,0,sizeof(maxcost)); 99 nodes.clear(); 100 dfs(0,-1,0); 101 double ans=-1; 102 for(int i=0;i<n;i++) 103 { 104 for(int j=i+1;j<n;j++) 105 { 106 ans=max(ans,(num[i]+num[j])/(tot-maxcost[i][j])); 107 } 108 } 109 printf("%.2lf ",ans); 110 } 111 return 0; 112 }