LA 5713 秦始皇修路

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\n",ans);
110     }
111     return 0;
112 }

 

posted @ 2017-05-18 11:19  Kayden_Cheung  阅读(351)  评论(0)    收藏  举报
//目录