HDU 4081 Qin Shi Huang's National Road System

https://vjudge.net/problem/HDU-4081

题意:

秦始皇想要修长城,修成生成树的样子,这是一个大师出现了,他说他可以不耗费人力修出一条路来。他们的目的很不一样,神特么有分歧,最后他们达成了一个协议,假设一个城市的人口为a。那么最后不耗费人力修的那条路所相连的两个城市的人力之和A与修路花费的人力B之比 A/B最大,并且输出最大值。

思路:

枚举去掉每一条边。

首先求出最小生成树,对于最小生成树中的每一条边,如果这条边不花费人力,那么直接计算A和B就可以了。

那么问题是如果选择的边不在最小生成树中的话,应该怎么办。为了形成生成树,肯定要将最小生成树生成树中的边去掉,又为了保持边的权值之和是最小的,所以自然想到了次小生成树,用到了maxn[u][v]那个数组,所以就将maxn[u][v]减去进行比较就行了。maxn[u][v]的求法请见次小生成树学习的博文。

  1 #include <stdio.h>
  2 #include <string.h>
  3 #include <algorithm>
  4 #include <math.h>
  5 #include <vector>
  6 #include <queue>
  7 using namespace std;
  8
  9 struct node
 10 {
 11     int x,y;
 12     double len;
 13 } a[1000005];
 14
 15 struct com
 16 {
 17     int id;
 18     double dis;
 19 };
 20
 21 int h[1005],z[1005],p[1005];
 22 int par[1005];
 23 bool v[1000005];
 24 double ma[1005][1005];
 25 bool vis[1005];
 26 vector<node> no[1005];
 27
 28 bool cmp(node aa,node bb)
 29 {
 30     if (aa.len == bb.len)
 31     {
 32         double t1 = p[aa.x] + p[aa.y];
 33         double t2 = p[bb.x] + p[bb.y];
 34
 35         return t2 < t1;
 36     }
 37
 38     return aa.len < bb.len;
 39 }
 40
 41 void init(int n)
 42 {
 43     for (int i = 0;i < n;i++)
 44         par[i] = i;
 45 }
 46
 47 int fin(int x)
 48 {
 49     if (x == par[x]) return x;
 50     else return par[x] = fin(par[x]);
 51 }
 52
 53 void unit(int x,int y)
 54 {
 55     x = fin(x);
 56     y = fin(y);
 57
 58     if (x != y) par[x] = y;
 59 }
 60
 61 double cal(int i,int j)
 62 {
 63     double dis1 = 1.0 * (h[i] - h[j]) * (h[i] - h[j]);
 64     double dis2 = 1.0 * (z[i] - z[j]) * (z[i] - z[j]);
 65
 66     return sqrt(dis1 + dis2);
 67 }
 68
 69 void adde(int x,int y,double dis)
 70 {
 71     node t;
 72
 73     t.x = x;
 74     t.y = y;
 75     t.len = dis;
 76
 77     no[x].push_back(t);
 78 }
 79
 80 void bfs(int k)
 81 {
 82     memset(vis,0,sizeof(vis));
 83
 84     com now,nex;
 85
 86     queue<com> qq;
 87
 88     while (!qq.empty()) qq.pop();
 89
 90     now.id = k;now.dis = 0;
 91     vis[now.id] = 1;
 92
 93     qq.push(now);
 94
 95     while (!qq.empty())
 96     {
 97         com tc = qq.front();qq.pop();
 98
 99         int tx = tc.id;
100         double maxn = tc.dis;
101
102         for (int i = 0;i < no[tx].size();i++)
103         {
104             node tmp = no[tx][i];
105             int ty = tmp.y;
106             double tmaxn = tmp.len;
107
108             if (!vis[ty])
109             {
110                 vis[ty] = 1;
111                 nex.id = ty;
112                 nex.dis = tmaxn;
113
114                 if (maxn > tmaxn) nex.dis = maxn;
115
116                 ma[k][ty] = nex.dis;
117
118                 qq.push(nex);
119             }
120         }
121     }
122 }
123
124 int main()
125 {
126     int t;
127
128     scanf("%d",&t);
129
130     while (t--)
131     {
132         int n;
133
134         scanf("%d",&n);
135
136         init(n);
137         memset(a,0,sizeof(a));
138         memset(v,0,sizeof(v));
139         memset(no,0,sizeof(no));
140
141         for (int i = 0;i < n;i++)
142         {
143             scanf("%d%d%d",&h[i],&z[i],&p[i]);
144         }
145
146         int cnt = 0;
147
148         for (int i = 0;i < n;i++)
149             for (int j = i + 1;j < n;j++)
150         {
151             a[cnt].x = i;a[cnt].y = j;
152             a[cnt].len  = cal(i,j);
153             cnt++;
154         }
155
156         double es = 0;
157
158         sort(a,a+cnt,cmp);
159
160         for (int i = 0;i < cnt;i++)
161         {
162             int x = a[i].x,y = a[i].y;
163
164             if (fin(x) == fin(y)) continue;
165
166             unit(x,y);
167
168             v[i] = 1;
169
170             adde(x,y,a[i].len);
171             adde(y,x,a[i].len);
172
173             es += a[i].len;
174         }
175
176         double maxn = 0;
177
178         for (int i = 1;i <= n;i++)
179         {
180             bfs(i);
181         }
182
183         for (int i = 0;i < cnt;i++)
184         {
185             if (v[i])
186             {
187                 double ns = 0;
188                 int x = a[i].x,y = a[i].y;
189
190                 ns += p[x];ns += p[y];
191
192                 es -= a[i].len;
193
194                 if (ns / es > maxn) maxn = ns / es;
195
196                 es += a[i].len;
197             }
198             else
199             {
200                 double ns = 0;
201                 int x = a[i].x,y = a[i].y;
202
203                 ns += p[x];ns += p[y];
204
205                 es -= ma[x][y];
206
207                 if (ns / es > maxn) maxn = ns / es;
208
209                 es += ma[x][y];
210             }
211         }
212
213         printf("%.2f\n",maxn);
214     }
215
216     return 0;
217 }

HDU 4081 Qin Shi Huang's National Road System

时间: 2024-10-10 10:41:08

HDU 4081 Qin Shi Huang's National Road System的相关文章

HDU 4081 Qin Shi Huang&#39;s National Road System 最小生成树

分析:http://www.cnblogs.com/wally/archive/2013/02/04/2892194.html 这个题就是多一个限制,就是求包含每条边的最小生成树,这个求出原始最小生成树然后查询就好了 然后预处理那个数组是O(n^2)的,这样总时间复杂度是O(n^2+m) 这是因为这个题n比较小,如果n大的时候,就需要路径查询了,比如LCA 或者树链剖分达到O(mlogn) #include <iostream> #include <algorithm> #incl

hdu 4081 Qin Shi Huang&#39;s National Road System(最小生成树+dp)

同样是看别人题解才明白的 题目大意—— 话说秦始皇统一六国之后,打算修路.他要用n-1条路,将n个城市连接起来,并且使这n-1条路的距离之和最短.最小生成树是不是?不对,还有呢.接着,一个自称徐福的游方道士突然出现,他说他可以不消耗任何人力财力,使用法术凭空造一条路,路的长度无所谓,但是只能造一条.那么问题来了,徐福希望将两座人口数最多的城市连接起来,而秦始皇希望将最长的路修好.最后折中了一下, 将A/B最大的一条路用法术修出来.其中A是两座城市的人口和,B是除了用法术修的路以外,其它需要修建的

HDU 4081 Qin Shi Huang&#39;s National Road System(最小生成树/次小生成树)

题目链接:传送门 题意: 有n坐城市,知道每坐城市的坐标和人口.现在要在所有城市之间修路,保证每个城市都能相连,并且保证A/B 最大,所有路径的花费和最小,A是某条路i两端城市人口的和,B表示除路i以外所有路的花费的和(路径i的花费为0). 分析: 先求一棵最小生成树,然后枚举每一条最小生成树上的边,删掉后变成两个生成树,然后找两个集合中点权最大的两 个连接起来.这两个点中必然有权值最大的那个点,所以直接从权值最大的点开始dfs. 为了使A/B的值最大,则A尽可能大,B尽可能小.所以B中的边一定

hdu 4081 Qin Shi Huang&#39;s National Road System 次小生成树 算法

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4180    Accepted Submission(s): 1450 Problem Description During the Warring States Period of ancient China(4

HDU 4081 Qin Shi Huang&#39;s National Road System(最小生成树+暴力枚举边)

题目大意:给你1000个点,每个点上有一个数目代表这个城市有多少人,让你把这N个点构成一颗生成树,你可以删除其中的任意一条边.让你求出一个比例A/B是的这个比例最大,A表示你删除那条边上两个城市的人口数之和,B表示的是去掉这条变这可生成树上其他的边的总长度. 解体思路:先求出来最小生成树,然后暴力枚举生成树的边,B=总数-这条边的长度.A = 将这条连断开之后左右集合中权值最大的两个数的和. 这样保证了B最小的情况下,去找最大的A,所以是可行的解.生成树的同时建边,然后dfs找最大值. PS:这

HDU 4081—— Qin Shi Huang&#39;s National Road System——————【次小生成树、prim】

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5608    Accepted Submission(s): 1972 Problem Description During the Warring States Period of ancient China(47

hdu 4081 Qin Shi Huang&#39;s National Road System 树的基本性质 or 次小生成树

During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in China ---- they were Qi, Chu, Yan, Han, Zhao, Wei and Qin. Ying Zheng was the king of the kingdom Qin. Through 9 years of wars, he finally conquered all

hdu 4081 Qin Shi Huang&#39;s National Road System (次小生成树)

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3843    Accepted Submission(s): 1336 Problem Description During the Warring States Period of ancient China(47

HDU 4081 Qin Shi Huang&#39;s National Road System 次小生成树

给你n个城市 每个城市有一定数量的人 连接2个城市需要的花费是他们之间的距离 现在要建一颗最小生成树 可以免费建其中一条边 设A为免费的那条边连接的2个城市的人口之和 B为修建的最小生成树的花费 求最大的A/B 先求最小生成树 设总花费为totol 然后可以枚举免费的那条边 枚举边等于A确定 在这条在最小生成树里的情况下 求最小的B 如果这条边是最小生成树里的边 那么很容易求得B 拿totol减去这条边就行了 如果不是 那么把这条边加到最小生成树 会出现一个环 找到这个环最大的那条边剪掉 就是次