HDU 4081 Qin Shi Huang's national road system (sub-small Spanning Tree Algorithm)

Source: Internet
Author: User

Link:

Http://acm.hdu.edu.cn/showproblem.php? PID = 1, 4081


Question:

Problem descriptionduring the Warring States Period of your ent 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 uniied 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 cocould 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 people's life. A daoshi (some kind of Monk) named Xu Fu told Qin Shi Huang that he cocould build a road by magic and that
Magic road wocould cost no money and no labor. but Xu Fu cocould 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 your 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
Total length of none magic roads.
Wocould 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.


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


Outputfor each test case, print a line indicating the above mentioned maximum ratio A/B. The result shocould be rounded to 2 digits after decimal point.


Sample Input

241 1 201 2 30200 2 80200 1 10031 1 201 2 302 2 40
 


Sample output

65.0070.00
 


Source2011 Asia Beijing Regional Contest

Question:

In N cities, Qin Shihuang wants to build n-1 roads to connect them. He wants to start from any point and reach any other point. Qin Shihuang hoped that the sum of the n-1 route lengths would be the shortest. Then Xu Fu suddenly came out, saying that he had magic, and he could make any one of them out without human or financial resources.

Qin Shihuang hoped that Xu Fu could change the longest n-1 Road to be repaired, but Xu Fu hoped to change the one with the most required manpower. The manpower required for each road is the sum of the number of people in the two cities connected by this road.

In the end, Qin Shihuang gave a formula: A/B, A refers to the manpower required for Xu Fu to use magic to make the road, B is the sum of the path lengths of all The N-2 except the one changed by Xu Fu.



Analysis and Summary

To maximize the value of a/B, we first need to minimize the value of B, so we can first find the Minimum Spanning Tree of N cities. Then, I decided to use Xu Fu's magic to change it.

Therefore, each edge can be enumerated. Assume that the value of the minimum spanning tree is minmst, and the length of the edge in the enumeration is W [I] [J]. if this edge already belongs to the smallest generation tree, the final sub-value is a/(minmst-W [I] [J]). If this line does not belong to the smallest spanning tree, then adding the above side will have n sides, so there will be a ring, in order to make it a spanning tree, delete a tree in the ring. To minimize the number of spanning trees, we need to delete the path with the largest weight except the added edge. Assume that the weight of the deleted edge is path [I] [J],
That is a/(minmst-path [I] [J]).

The key to solving this problem is how to find the next generation tree.


The following is an excerpt from online materials:

[Secondary generation tree]

Similar to the preceding short path method, it is easy to think of an intuitive solution of "enumerative deletion of each edge of the Minimum Spanning Tree and then finding the Minimum Spanning Tree. If prim + is used for heap, the minimum time complexity of each spanning tree is O (n * log (n + M), and the enumeration deletes an O (n) edge, the time complexity is O (n ^ 2 * log (n + M) + N * m). When the graph is very dense, it is close to O (N ^ 3 ). This method is simple and intuitive, but we have a simpler and more efficient O (N ^ 2 + M) solution. The following describes this method.

First, find the Minimum Spanning Tree of the source image, and record the sum of weights to minst. Add each edge (u, v) that is not on the minimum generation tree to the enumeration. A ring will be formed after the addition. Find the edge with the second largest weight value on the ring (that is, the edge with the largest weight value except (u, v), delete it, and calculate the sum of the weights of the current spanning tree. Take the minimum value of the sum of the generated tree weights modified by all enumeration operations, that is, the next generation tree.

In specific implementation, the simpler method is to traverse the entire minimal spanning tree from each node I, and define f [J] as the maximum edge value in the path from I to J. Traverse the graph to find the value of F [J], and then add each edge (I, j) that is not in the minimum spanning tree. The sum of the newly generated tree weights is minst + W (I, j)-f [J]. If the minimum value is recorded, the Child tree is generated.

The time complexity of this algorithm is O (n ^ 2 + M ). Because only the minimum spanning tree is used, the simplest prim can be used. The time complexity is O (n ^ 2 ). The bottleneck of the algorithm is not to find the minimum spanning tree, but to add edge modifications to the enumeration of O (N ^ 2 + M), so it is unnecessary to use a better minimum spanning tree algorithm.


The algorithm for solving the next small Spanning Tree:

Convention: A set composed of a new spanning tree generated by T for a feasible exchange. It is called the adjacent set of tree T and is recorded as N (t ).
Theorem 3: Let t be the Minimum Spanning Tree of graph G. If T1 satisfies ω (T1) = min {ω (t') | T' ε N (t )}, then T1 is g
.
Proof: If T1 is not a small generation tree of G, there must be another generation tree t', T' = t to make
ω (t) ≤ ω (t') <ω (T1), defined by T1 t does not belong to N (t), then
E (t') \ E (t) = {A1, A2
1 ,......, At}, E (t) \ e (t') = {b1, b2 ,......, BT}, where T is greater than or equal to 2. According to the Theorem 1, there is
Bi1, bi2 ,......, Bit so that t + AJ-BIJ is still a G Spanning Tree and belongs to N (t), so ω (AJ) ≥ ω (BIJ ),
Therefore, ω (t') ≥ ω (t + AJ-BIJ) ≥ ω (T1) is a conflict. So T1 is the next generation tree of graph G.
Through the above theorem, we have a basic idea to solve the problem of sub-tree generation.
First, find the minimum spanning tree T of the graph. Time complexity O (vlog2v + E)
Then, calculate the weights of the neighboring sets of T and the smallest spanning tree, that is, the secondary Spanning Tree of graph G.
For simple enumeration, the complexity is very high. The complexity of enumerating the two sides is O (VE), and then determining whether the exchange is
The feasible complexity is O (v), and the total time complexity is O (v2e ). Such algorithms seem blind. After a simple
It is not difficult to find that every edge added to a tree can always form a ring. Only one edge on the ring can be deleted.
After the switch, make sure that the tree is still generated. The larger the value of the deleted edge, the smaller the sum of the newly generated tree values. We can
To reduce the complexity to O (VE ). This is a huge step forward, but it is still not good enough.
Looking back at the previous model-minimum limit spanning tree, we have encountered similar problems and finally adopted dynamic rules.
The drag method avoids Repeated Computation, greatly reducing the complexity. We can use similar ideas for this question. First
First, perform step preprocessing to find the edge with the largest weight value on the path between each two nodes in the tree.
With the preprocessing of the edge on the tree, we can use the O (1) Time to obtain the edge with the largest weight on the ring.
How to pre-process it? Because this is a tree, there is no need for advanced algorithms, as long as a simple BFs.
The time complexity required for preprocessing is O (V2 ).
In this way, the time complexity of this step is reduced to O (V2 ).
To sum up, the time complexity of the next minor generation tree is O (V2 ).

Conclusion 1
The secondary spanning tree can be obtained by an edge of the smallest spanning tree.

Proof:
The following is a strong conclusion:
T is a minimum spanning tree, t0 is a tree different from T.
T0 --> T1 --> T2 -->... --> TN (t) is changed to the Minimum Spanning Tree.
The so-called transformation is to replace an edge in Ti with an edge in T, and
And the tree T (I + 1) has a weight less than or equal to Ti.
The specific operation is:
Step 1. in Ti, take an edge UV that is not in T.
Step 2. Remove edge UV, and there are two connected components A and B,
In T, there must be a unique edge U 'V' linking A and B.
Step 3. Obviously, u'v' has a smaller weight than UV (otherwise, UV should be in T ).
Replace u'v' with UV to get the tree T (I + 1 ).
Specifically: Take t0 as any minor tree, T (n-1) is also the minor tree and
A side different from T. Conclusion 1 proves.

Algorithm:
Make full use of conclusion 1, that is, the V ^ 2 algorithm. The details are as follows:

Step 1. Use prim to find the minimum spanning tree T.
At the same time as prim, use a matrix MAX [u] [v] to record the unique
The weight of the edge with the largest weight in the path. (note here ).
This is easy to do, because prim adds a node s each time, and sets the labeled Node
If the set is W, the edge of the maximum weight from all vertices in W to S is the edge currently added.
O (V ^ 2) for step 1 ).
Step 2. enumerate all edge Uvs that are not in T. Adding edge Uvs will inevitably replace the edges with the Max [u] [v] weight.

Therefore, the total time is O (V ^ 2 ).




Code:

#include<cstdio>#include<cstring>#include<iostream>#include<cmath>#define INF 2147483647#define N 1005using namespace std;double G[N][N],  minCost[N], pos[N][2], path[N][N], cost[N], ratio, A, B;int pre[N], hash[N], n;bool used[N][N];inline double getDist(double x1,double y1,double x2,double y2){    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));}double Prim(){    A=B=0;    memset(hash, 0, sizeof(hash));    memset(used, 0, sizeof(used));    memset(path, 0, sizeof(path));    hash[1]=1;    for(int i=1; i<=n; ++i){        minCost[i] = G[1][i];        pre[i] = 1;    }    for(int i=1; i<n; ++i){        int u=-1;        for(int j=1; j<=n; ++j)if(!hash[j]){            if(u==-1 || minCost[j]<minCost[u])                u = j;        }        used[u][pre[u]]=used[pre[u]][u] = true;        B += G[pre[u]][u];        hash[u] = 1;        for(int j=1; j<=n; ++j){            if(hash[j]&&j!=u){                path[u][j]=path[j][u]=max(path[j][pre[u]], minCost[u]);             }             if(!hash[j]){                if(minCost[j]>G[u][j]){                    minCost[j] = G[u][j];                    pre[j] = u;                }            }        }    }    return B;}int main(){    int T;    scanf("%d",&T);    while(T--){        scanf("%d",&n);        memset(G, 0, sizeof(G));        for(int i=1; i<=n; ++i)            scanf("%lf%lf%lf",&pos[i][0],&pos[i][1],&cost[i]);        for(int i=1; i<=n; ++i){            for(int j=1; j<=n; ++j)if(i!=j){                G[i][j] = getDist(pos[i][0],pos[i][1],pos[j][0],pos[j][1]);            }        }        Prim();        ratio = -1;        for(int i=1; i<=n; ++i){            for(int j=1; j<=n; ++j)if(i!=j){                if(used[i][j]){                    ratio = max(ratio, (cost[i]+cost[j])/(B-G[i][j]));                }                else{                    ratio = max(ratio, (cost[i]+cost[j])/(B-path[i][j]));                }            }        }        printf("%.2f\n", ratio);    }    return 0;}

-- The meaning of life is to give it meaning.

Original Http://blog.csdn.net/shuangde800 , By d_double (reprinted, please mark)

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.