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代表所建的魔法路的连接的城市的市民的人数 ...
随机推荐
- Python学习笔记:time模块和datetime模块(时间和日期)
time模块 time模块通常用来操作时间戳信息(各种“秒”),常用的方法有: time.sleep(seconds):将当前程序阻塞指定秒数,然后继续运行程序. time.time():返回当前时间 ...
- matplotlib 设置图形大小时 figsize 与 dpi 的关系
matplotlib 中设置图形大小的语句如下: fig = plt.figure(figsize=(a, b), dpi=dpi) 其中: figsize 设置图形的大小,a 为图形的宽, b 为图 ...
- WZK的减肥计划
WZK 的减肥计划(plan.cpp/ plan.in/ plan.out)问题描述:WZK 发现他的体重正迅猛的上升着,对此他感到非常焦虑,想要制定出一套完美的减肥计划. 于是 WZK 翻阅资料,查 ...
- NSNotificationCenter的用法
作用:NSNotificationCenter是专门供程序中不同类间的消息通信而设置的. 注册通知:即要在什么地方接受消息 [[NSNotificationCenter defaultCenter] ...
- UVa 1452 递推 Jump
约瑟夫变形,先计算出3个数时,最后三个数字的编号. 然后以这三个数为起点,就可以递推出n个数对应的最后三个数字的编号. 递推公式都是一样的. #include <iostream> #in ...
- javascript基础1 语法 点击事件 超链接带点击事件
javascript ----------------------------------------------------------------------------------------- ...
- JDBC 学习笔记(七)—— CallableStatement
在大型关系型数据库中,有一组为了完成特定功能的 SQL 语句集被称为存储过程(Stored Procedure),它是数据库中的对象. JDBC 使用 CallableStatement 对象,完成对 ...
- BZOJ4176 Lucas的数论 【莫比乌斯反演 + 杜教筛】
题目 去年的Lucas非常喜欢数论题,但是一年以后的Lucas却不那么喜欢了. 在整理以前的试题时,发现了这样一道题目"求Sigma(f(i)),其中1<=i<=N", ...
- 刷题总结——分配笔名(51nod1526 trie树)
题目: 班里有n个同学.老师为他们选了n个笔名.现在要把这些笔名分配给每一个同学,每一个同学分配到一个笔名,每一个笔名必须分配给某个同学.现在定义笔名和真名之间的相关度是他们之间的最长公共前缀.设笔名 ...
- 【2018.12.17】NOI模拟赛4
题目 WZJ题解 T1 T2 T3 后缀自动机+($parents$ 树)树链剖分 发现有大量子串需要考虑,考虑摁死子串的一端. 首先,这题显然是一道离线题,因为所有的询问都是 $1$ 到 某个数,也 ...