原题链接: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

Problem Description
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 six other kingdoms and became the first emperor of a unified China in 221 BC. That was Qin dynasty ---- the first imperial dynasty of China(not to be confused with the Qing Dynasty, the last dynasty of China). So Ying Zheng named himself "Qin Shi Huang" because "Shi Huang" means "the first emperor" in Chinese.

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.
 
Input
The first line contains an integer t meaning that there are t test cases(t <= 10).
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.
 
Output
For each test case, print a line indicating the above mentioned maximum ratio A/B. The result should be rounded to 2 digits after decimal point.
 
Sample Input
2
4
1 1 20
1 2 30
200 2 80
200 1 100
3
1 1 20
1 2 30
2 2 40
 
Sample Output
65.00
70.00
 
Source
 
Recommend
lcy

题意:

给你平面上若干的点,每个点有个权值$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的更多相关文章

  1. HDU 4081 Qin Shi Huang's National Road System 最小生成树

    分析:http://www.cnblogs.com/wally/archive/2013/02/04/2892194.html 这个题就是多一个限制,就是求包含每条边的最小生成树,这个求出原始最小生成 ...

  2. 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 ...

  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 ...

  4. 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 ...

  5. 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 ...

  6. 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 ...

  7. HDU - 4081 Qin Shi Huang's National Road System 【次小生成树】

    题目链接 http://acm.hdu.edu.cn/showproblem.php?pid=4081 题意 给出n个城市的坐标 以及 每个城市里面有多少人 秦始皇想造路 让每个城市都连通 (直接或者 ...

  8. hdu 4081 Qin Shi Huang's National Road System(次小生成树prim)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4081 题意:有n个城市,秦始皇要修用n-1条路把它们连起来,要求从任一点出发,都可以到达其它的任意点. ...

  9. HDU 4081 Qin Shi Huang's National Road System [次小生成树]

    题意: 秦始皇要建路,一共有n个城市,建n-1条路连接. 给了n个城市的坐标和每个城市的人数. 然后建n-2条正常路和n-1条魔法路,最后求A/B的最大值. A代表所建的魔法路的连接的城市的市民的人数 ...

随机推荐

  1. 面向对象之元类(metaclass)

    一.前言: 要搞懂元类必须要搞清楚下面几件事: 类创建的时候,内部过程是什么样的,也就是我们定义类class 类名()的过程底层都干了些啥 类的调用即类的实例化过程的了解与分析 我们已经知道元类存在的 ...

  2. NXP低功耗蓝牙集成芯片QN9080C的时钟配置

    /*************************************************************************************************** ...

  3. Linux 关于SELinux的命令及使用

    1. 模式的设置 : 修改/etc/selinux/config文件中的SELINUX=”" 的值 ,然后重启.enforcing:强制模式,只要selinux不允许,就无法执行 permi ...

  4. jquery如何获取某一个兄弟节点

    $('#id').siblings() 当前元素所有的兄弟节点 $('#id').prev() 当前元素前一个兄弟节点 $('#id').prevaAll() 当前元素之前所有的兄弟节点 $('#id ...

  5. Selenium WebDriver- 操作JavaScript的confirm弹窗

    #encoding=utf-8 import unittest import time from selenium import webdriver from selenium.webdriver i ...

  6. bootstrap里的fileimput的小问题

    fileinput 是bootstrap 里面一个非常好的插件 于是我很开心的开始的使用了 $("#file_upload").fileinput({ uploadUrl: &qu ...

  7. c4d 宝典部分二

    一.tvart 文字 1.当选择工具 选择面或边时不出现对象坐标时,需要将容错的选项选中 2.当选择两个面右键挤压的时候,如果两个面不分离,需要取消群组并且 拉动箭头的时候需要在空白区域拉动 tvar ...

  8. Baum Welch估计HMM参数实例

    Baum Welch估计HMM参数实例 下面的例子来自于<What is the expectation maximization algorithm?> 题面是:假设你有两枚硬币A与B, ...

  9. Tensorflow 笔记 -- tensorboard 的使用

    Tensorflow 笔记 -- tensorboard 的使用 TensorFlow提供非常方便的可视化命令Tensorboard,先上代码 import tensorflow as tf a = ...

  10. 项目记事【多线程】:关于 SimpledDateFormat 的多线程问题

    背景: 最近项目引入了 SonarLink,解决代码规范的问题,在检查历史代码的时候,发现了一个问题. 先看代码: public class DateUtil { private static fin ...