HDU 4081 Qin Shi Huang's National Road System 最小生成树+倍增求LCA
原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081
Qin Shi Huang's National Road System
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 5428 Accepted Submission(s): 1902

Qin Shi Huang undertook gigantic projects, including the first version of the Great Wall of China, the now famous city-sized mausoleum guarded by a life-sized Terracotta Army, and a massive national road system. There is a story about the road system:
There were n cities in China and Qin Shi Huang wanted them all be connected by n-1 roads, in order that he could go to every city from the capital city Xianyang.
Although Qin Shi Huang was a tyrant, he wanted the total length of all roads to be minimum,so that the road system may not cost too many people's life. A daoshi (some kind of monk) named Xu Fu told Qin Shi Huang that he could build a road by magic and that magic road would cost no money and no labor. But Xu Fu could only build ONE magic road for Qin Shi Huang. So Qin Shi Huang had to decide where to build the magic road. Qin Shi Huang wanted the total length of all none magic roads to be as small as possible, but Xu Fu wanted the magic road to benefit as many people as possible ---- So Qin Shi Huang decided that the value of A/B (the ratio of A to B) must be the maximum, which A is the total population of the two cites connected by the magic road, and B is the total length of none magic roads.
Would you help Qin Shi Huang?
A city can be considered as a point, and a road can be considered as a line segment connecting two points.
For each test case:
The first line is an integer n meaning that there are n cities(2 < n <= 1000).
Then n lines follow. Each line contains three integers X, Y and P ( 0 <= X, Y <= 1000, 0 < P < 100000). (X, Y) is the coordinate of a city and P is the population of that city.
It is guaranteed that each city has a distinct location.
4
1 1 20
1 2 30
200 2 80
200 1 100
3
1 1 20
1 2 30
2 2 40
70.00
题意:
给你平面上若干的点,每个点有个权值$a_i$,现在用这些点构成一棵树。存在一种操作,可以使得这棵树上的某条边的长度变为0,令这条边连接的两个点分别是$i,j$,这棵树的边权和为$B$,问你$(a_i+a_j)/B$的最小值。
题解:
看网上的做法都是求次小生成树,而我却不是这样做的。
首先使用Kruskal求出最小生成树,而后枚举两个点,将这两个点之间连接那条边,这样就构成了一个换,为了保持树的形态,必须删掉这两个点的唯一路径上最长的边。
找到这条边的方法是通过倍增来求解。
令$ancestor[u][i]$为节点$u$向上走$2^i$所能到达的节点,$maxEdge[u][i]$表示节点$u$向上走$2^i$所能碰到的最长的边,那么有以下转移:
$$ancestor[u][i]=ancestor[ancestor[u][i-1]][i-1]$$
$$maxEdge[u][i]=max(maxEdge[u][i-1],maxEdge[ancestor[u][i-1]][i-1])$$
预处理出这两个数组后,就能用类似LCA的思想求最长边了。
代码:
#include<iostream>
#include<cstring>
#include<vector>
#include<cstdio>
#include<algorithm>
#include<iomanip>
#define MAX_N 1234
#define MAX_D 25
using namespace std; int father[MAX_N];
int n; int popu[MAX_N]; struct edge {
int to;
double cost; edge(int t, double c) : to(t), cost(c) { } edge() { }
}; struct road {
int from, to;
double cost; road(int f, int t, double c) : from(f), to(t), cost(c) { } road() { }
}; bool cmp(road a,road b) {
if (a.cost == b.cost)
return popu[a.from] + popu[a.to] > popu[b.from] + popu[b.to];
return a.cost < b.cost;
} road ro[MAX_N*MAX_N];
int tot=;
vector<edge> G[MAX_N];
double B; int depth[MAX_N];
int ancestor[MAX_N][];
double maxEdge[MAX_N][]; struct Point {
double x, y; Point(double xx, double yy) : x(xx), y(yy) { } Point() { } double dis(Point a) {
return sqrt((x - a.x) * (x - a.x) + (y - a.y) * (y - a.y));
}
}; Point po[MAX_N]; void init() {
for (int i = ; i <= n; i++)
father[i] = i;
for (int i = ; i <= n; i++)G[i].clear();
tot = ;
B = ;
memset(depth, , sizeof(depth));
memset(ancestor, , sizeof(ancestor));
memset(maxEdge, , sizeof(maxEdge));
} int Find(int x){
if(x==father[x])return x;
return father[x]=Find(father[x]);
} void unionSet(int x,int y) {
int u = Find(x), v = Find(y);
if (u == v)return;
father[u] = v;
} bool Same(int x,int y){
return Find(x)==Find(y);
} void Kruskal() {
sort(ro + , ro + tot + , cmp);
for (int i = ; i <= tot; i++) {
int u = ro[i].from, v = ro[i].to;
if (Same(u, v))continue;
unionSet(u, v);
G[u].push_back(edge(v,ro[i].cost));
G[v].push_back(edge(u,ro[i].cost));
B += ro[i].cost;
}
} void dfs(int u,int p) {
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i].to;
double c = G[u][i].cost;
if (v == p)continue;
depth[v] = depth[u] + ;
ancestor[v][] = u;
maxEdge[v][] = c;
dfs(v, u);
}
} void getAncestor() {
for (int j = ; j < MAX_D; j++) {
for (int i = ; i <= n; i++) {
ancestor[i][j] = ancestor[ancestor[i][j - ]][j - ];
maxEdge[i][j] = max(maxEdge[i][j - ], maxEdge[ancestor[i][j - ]][j - ]);
}
}
} double LCA(int u,int v) {
double res = -;
if (depth[u] < depth[v])swap(u, v);
for (int i = MAX_D - ; i >= ; i--) {
if (depth[ancestor[u][i]] >= depth[v]) {
res = max(res, maxEdge[u][i]);
u = ancestor[u][i];
if (depth[u] == depth[v])break;
}
}
if (u == v)return res;
for (int i = MAX_D - ; i >= ; i--) {
if (ancestor[u][i] != ancestor[v][i]) {
res = max(res, max(maxEdge[u][i], maxEdge[v][i]));
u = ancestor[u][i];
v = ancestor[v][i];
}
}
return max(res, max(maxEdge[u][], maxEdge[v][]));
} int T; int main() {
cin.sync_with_stdio(false);
cin >> T;
while (T--) {
cin >> n;
init();
for (int i = ; i <= n; i++)
cin >> po[i].x >> po[i].y >> popu[i];
for (int i = ; i <= n; i++)
for (int j = i + ; j <= n; j++)
ro[++tot] = road(i, j, po[i].dis(po[j]));
Kruskal();
depth[] = ;
dfs(, );
getAncestor();
double ans = -;
for (int i = ; i <= n; i++)
for (int j = ; j <= n; j++)
ans = max(ans, (popu[i] + popu[j]) / (B - LCA(i, j)));
cout << setprecision() << fixed << ans << endl;
}
return ;
}
PS:第一次写手写倍增,居然一发就AC了
HDU 4081 Qin Shi Huang's National Road System 最小生成树+倍增求LCA的更多相关文章
- HDU 4081 Qin Shi Huang's National Road System 最小生成树
分析:http://www.cnblogs.com/wally/archive/2013/02/04/2892194.html 这个题就是多一个限制,就是求包含每条边的最小生成树,这个求出原始最小生成 ...
- HDU 4081 Qin Shi Huang's National Road System 次小生成树变种
Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3 ...
- hdu 4081 Qin Shi Huang's National Road System (次小生成树)
Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3 ...
- hdu 4081 Qin Shi Huang's National Road System (次小生成树的变形)
题目:Qin Shi Huang's National Road System Qin Shi Huang's National Road System Time Limit: 2000/1000 M ...
- HDU 4081—— Qin Shi Huang's National Road System——————【次小生成树、prim】
Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/3 ...
- hdu 4081 Qin Shi Huang's National Road System 树的基本性质 or 次小生成树思想 难度:1
During the Warring States Period of ancient China(476 BC to 221 BC), there were seven kingdoms in Ch ...
- HDU - 4081 Qin Shi Huang's National Road System 【次小生成树】
题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4081 题意 给出n个城市的坐标 以及 每个城市里面有多少人 秦始皇想造路 让每个城市都连通 (直接或者 ...
- hdu 4081 Qin Shi Huang's National Road System(次小生成树prim)
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081 题意:有n个城市,秦始皇要修用n-1条路把它们连起来,要求从任一点出发,都可以到达其它的任意点. ...
- HDU 4081 Qin Shi Huang's National Road System [次小生成树]
题意: 秦始皇要建路,一共有n个城市,建n-1条路连接. 给了n个城市的坐标和每个城市的人数. 然后建n-2条正常路和n-1条魔法路,最后求A/B的最大值. A代表所建的魔法路的连接的城市的市民的人数 ...
随机推荐
- HDU:4185-棋盘游戏
棋盘游戏 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Problem Descri ...
- selenium2中TestNG相关解释
testNg官网:http://testng.org/doc/documentation-main.html 新建testNG class的时候,同时也新建了一个TestNG.xml的文件. 此xml ...
- Java基础之封装
封装(Encapsulation)是java面向对象的三大特性,之前学java迷迷糊糊,一直也没弄清楚什么是封装以及为什么要封装,直到这次看书才有一种被点醒的感觉. java中的封装是针对某个类而言的 ...
- 当列表推导式遇到lambda(匿名函数)
Python这么优雅的语言,我也是醉了...... 事情由一段代码引发,请看: 上述的列表推导式+lambda表达式+for循环,他们碰撞出来的结果搞的人晕头转向,咱们逐步来分析一下他们到底是个什么鬼 ...
- 03008_ServletContext
1.什么是ServletContext? (1)ServletContext代表是一个web应用的环境(上下文)对象,ServletContext对象 内部封装是该web应用的信息,Servle ...
- Jenkins自动化搭建测试环境(一)
Jenkins基础 首先上官网jenkins.io上下载最新的Jenkins war包 将下载完成的war包解压 java -jar jenkins.war 接下来使用浏览器访问localhost:8 ...
- [POJ 1002] 487-3279 C++解题报告
487-3279 Time Limit: 2000MS Memory Limit: 65536K Total Submissions: 228365 Accepted: 39826 D ...
- 【转】LAMP网站架构方案分析【精辟】
[转]LAMP网站架构方案分析[精辟] http://www.cnblogs.com/mo-beifeng/archive/2011/09/13/2175197.html Xubuntu下LAMP环境 ...
- Python面试题(练习一)
1.Python的可变类型和不可变类型? 可变类型:list.dict(列表和字典) 不可变类型:数字.字符串.元组 2.求结果: v = dict.fromkeys(['k1','k2'],[]) ...
- python常用方法总结
1.os模块的路径拼接: import os now_path=os.path.abspath(__file__)#当前运行文件的路径 print(now_path) uppeer_path=os.p ...