首页 > 代码库 > HDU4081 Qin Shi Huang's National Road System【Kruska】【次小生成树】
HDU4081 Qin Shi Huang's National Road System【Kruska】【次小生成树】
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
2011 Asia Beijing Regional Contest
题目大意:有N个城市,秦始皇要用N-1条路将他们全部连起来,秦始皇希望这N-1条路长度
之和最短。这时候,徐福跳出来说他有魔法,可以凭空变出其中任意一条路来。
秦始皇希望徐福将N-1条路中最长的那条路变出来,但是徐福希望把修路要求人数最多的那条
路变出来(每条路修路的人力是两座城市的人口和)。最终,秦始皇给出了一个公式 A/B
徐福变出的那条路所需人力/除了这条路之外的N-2条路的和 最大。
简化大意为:给你N个城市的坐标(x,y)和人口。 得到他的最小生成树之后,去掉最小生成树上
的一条边,使得这条路两边连接城市的人数和/最小生成树上其他N-2条路的长度和(A/B)最大。
输出这个最大的比值。
思路:为了使得上述公式A/B比值最大,就需要B尽可能小。
先求出最小生成树MST,再选择要删去哪一条边,可以遍历MST上的边,假设枚举的边长度为
Len[i][j],最终结果就为max(A/MST-Len[i][j])(1<=i<=n,i+1<=j<=n)。其中A为最小生成树
上的边。若A不是最小生成树上的边。最小生成树加上A边就会成为一个环。为了使得他原先为
一个生成树,就要删去这个环上除了A边外权值最大的边,就是原先最小生成树中权值最大的边。
最终结果还是max(A/MST-Len[i][j])(1<=i<=n,i+1<=j<=n)。而加上A边所形成的生成树其实
就是次小生成树。所以问题就转换为求次小生成树,再遍历求结果。
注意:代码用C++提交就超时,G++提交就AC。不知道什么情况。。。按理说C++比G++高效
才对。不知道是什么原因~求大神给解释解释哈~感激不尽。
参考博文:http://tech.ddvip.com/2013-10/1380576235203623.html
#include<algorithm> #include<cstdio> #include<cstring> #include<cmath> using namespace std; const int MAXN = 1010; const int MAXM = 1000010; int father[MAXN]; int find(int x) { if(x != father[x]) father[x] = find(father[x]); return father[x]; } struct Node { int from; int to; double w; }; Node Edges[MAXM]; bool cmp(Node a,Node b) { return a.w < b.w; } struct Node1 { int to; int next; }; Node1 Vertex[MAXN]; struct Node2 { int x; int y; double d; }; Node2 Point[MAXN]; double Dist(int i,int j) { double x = Point[i].x - Point[j].x; double y = Point[i].y - Point[j].y; return sqrt(x*x+y*y); } int N,M,Head[MAXN],End[MAXN]; double Len[MAXN][MAXN]; double Kruskal() { int i,x,y,w,v,k = 0; double ans = 0; for(i = 1; i <= N; ++i) { Vertex[i].to = i; Vertex[i].next = -1; Head[i] = End[i] = i; } for(i = 0; i < M; ++i) { if(k == N-1) break; if(Edges[i].w < 0) continue; x = find(Edges[i].from); y = find(Edges[i].to); if(x != y) { for(w = Head[x]; w != -1; w = Vertex[w].next) { for(v = Head[y]; v != -1; v = Vertex[v].next) { Len[Vertex[w].to][Vertex[v].to] = Len[Vertex[v].to][Vertex[w].to] = Edges[i].w; } } father[y] = x;//改为father[x] = y就错 Vertex[End[y]].next = Head[x]; Head[x] = Head[y]; k++; ans += Edges[i].w; if(k == N-1) break; } } return ans; } double maxv(double a,double b) { return a > b ? a : b; } int main() { int T,i,j; scanf("%d",&T); while(T--) { scanf("%d",&N); for(i = 1; i <= N; ++i) father[i] = i; for(i = 1; i <= N; ++i) { scanf("%d%d%lf",&Point[i].x,&Point[i].y,&Point[i].d); } M = 0; for(i = 1; i <= N; ++i) { for(j = i+1; j <= N; ++j) { Edges[M].from = i; Edges[M].to = j; Edges[M++].w = Dist(i,j); } } sort(Edges,Edges+M,cmp); double MST = Kruskal(); double ans = 0; for(i = 1; i <= N; ++i) { for(j = i+1; j <= N; ++j) ans = maxv(ans,(Point[i].d + Point[j].d)/(MST-Len[i][j])); } printf("%.2lf\n",ans); } return 0; }
HDU4081 Qin Shi Huang's National Road System【Kruska】【次小生成树】