HDU4081 Qin Shi Huang's National Road System【Kruska】【次小生成树】

Qin Shi Huang‘s National Road System

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)

Total Submission(s): 3979    Accepted Submission(s): 1372

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】【次小生成树】

时间: 2024-10-09 07:35:49

HDU4081 Qin Shi Huang's National Road System【Kruska】【次小生成树】的相关文章

HDU4081 Qin Shi Huang&#39;s National Road System(次小生成树)

枚举作为magic road的边,然后求出A/B. A/B得在大概O(1)的时间复杂度求出,关键是B,B是包含magic road的最小生成树. 这么求得: 先在原图求MST,边总和记为s,顺便求出MST上任意两点路径上的最长边d[i][j]. 当(u,v)是magic road时, 如果它在原本的MST上,则B就等于s-原(u,v)的权,而原(u,v)的权其实就是d[u][v]: 如果它不在原本的MST上,则B就等于s-d[u][v]+0. 总之就是一个式子:B=s-d[u][v]. 于是,在

HDU4081 Qin Shi Huang&#39;s National Road System 【次小生成树】

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3395    Accepted Submission(s): 1189 Problem Description During the Warring States Period of ancient China(4

UVA - 1494 Qin Shi Huang&#39;s National Road System (类次小生成树)

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 con

HDU 4081 Qin Shi Huang&#39;s National Road System(最小生成树/次小生成树)

题目链接:传送门 题意: 有n坐城市,知道每坐城市的坐标和人口.现在要在所有城市之间修路,保证每个城市都能相连,并且保证A/B 最大,所有路径的花费和最小,A是某条路i两端城市人口的和,B表示除路i以外所有路的花费的和(路径i的花费为0). 分析: 先求一棵最小生成树,然后枚举每一条最小生成树上的边,删掉后变成两个生成树,然后找两个集合中点权最大的两 个连接起来.这两个点中必然有权值最大的那个点,所以直接从权值最大的点开始dfs. 为了使A/B的值最大,则A尽可能大,B尽可能小.所以B中的边一定

HDU 4081—— Qin Shi Huang&#39;s National Road System——————【次小生成树、prim】

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 5608    Accepted Submission(s): 1972 Problem Description During the Warring States Period of ancient China(47

hdu 4081 Qin Shi Huang&#39;s National Road System (次小生成树)

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3843    Accepted Submission(s): 1336 Problem Description During the Warring States Period of ancient China(47

hdu4081 Qin Shi Huang&#39;s National Road System 次小生成树

先发发牢骚:图论500题上说这题是最小生成树+DFS,网上搜题解也有人这么做.但是其实就是次小生成树.次小生成树完全当模版题.其中有一个小细节没注意,导致我几个小时一直在找错.有了模版要会用模版,然后慢慢融会贯通.我要走的路还长着啊. 讲讲次小生成树的思想吧.首先,在prim算法中做一些改变,求出任意两点(u,v)路径之间的最大权值,并记录,记为maxe[u][v].运行遍prim算法.枚举每一条边,如果该边是属于最小生成树的边,则ratio=(value(u) +value(v) ) /( a

HDU4081 Qin Shi Huang&#39;s National Road System【prim最小生成树+枚举】

先求出最小生成树,然后枚举树上的边,对于每条边"分别"找出这条割边形成的两个块中点权最大的两个 1.由于结果是A/B,A的变化会引起B的变化,两个制约,无法直接贪心出最大的A/B,故要通过枚举 2.不管magic road要加在哪里,加的边是否是最小生成树上的边,都会产生环,我们都要选择一条边删掉 注意删掉的边必须是树的环上的边,为了使结果最大,即找出最大的边 3.可以枚举两点,找出边,也可以枚举边,找出点,我是用后者,感觉比较容易写也好理解 #include <cstdio&g

HDU-4081 Qin Shi Huang&#39;s National Road System(最小生成树)

今天比赛AC的一道最小生成树的题目 , 学到了不少东西 . 最小生成树的模板很简单,最简洁好写的还是lrj紫书上的代码 .利用并查集加速算法 . 该题的不同之处在于它选择任意一条路修成"魔法"道路 , 然后其他路的权值之和还要是最小的一棵次小生成树,并且求魔法道路两端点值之和除以其他路径长之和的最大值 . 显然该题的难点在于枚举两个端点之后怎么快速的求出次小生成树权值之和 .  枚举两个端点之后的复杂度已经是O(n^2),所以要想出一个快速的方法 . 受紫书上例题uva 1151 (传