HDU4081Qin Shi Huang's National Road System(最小生成树+DFS)

Qin Shi Huang‘s National Road System

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

Total Submission(s): 4227    Accepted Submission(s): 1465

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

#include<stdio.h>
#include<math.h>
#include<vector>
#include<string.h>
using namespace std;

const double inf=99999999;
const int N = 1005;
struct EDG
{
    int u,v;
};

int n,vist[N],P[N];
double node[N],map[N][N],sum,R;
vector<int>tmap[N];
EDG edg[N];

void prim(int s)
{
    int ts,k=0,f[N];
    double mint;
    for(int i=1;i<=n;i++)
        node[i]=inf,vist[i]=0;
    sum=0;
    vist[s]=1; node[s]=0; k++;

    while(k<n)
    {
        mint=inf;
        for(int i=1;i<=n;i++)
        if(vist[i]==0)
        {
            if(node[i]>map[s][i])
                node[i]=map[s][i],f[i]=s;
            if(mint>node[i])
                mint=node[i],ts=i;
        }
        sum+=mint;
        edg[k].u=f[ts]; edg[k].v=ts;
        tmap[f[ts]].push_back(ts);
        tmap[ts].push_back(f[ts]);
        s=ts; vist[s]=1; k++;
    }
}

int DFS(int s,int maxp)
{
    vist[s]=1;
    if(maxp<P[s])
        maxp=P[s];
    for(int i=0; i<tmap[s].size(); i++)
    {
        if(vist[tmap[s][i]])
            continue;
        maxp=DFS(tmap[s][i],maxp);
    }
    vist[s]=0;
    return maxp;
}
int main()
{
    int t;
    double x[N],y[N];

    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
            scanf("%lf%lf%d",&x[i],&y[i],&P[i]);
        for(int i=1;i<=n;i++)
        {
            tmap[i].clear();
            for(int j=1;j<=n;j++)
            map[i][j]=sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
        }

        prim(1);
        R=-1;
        memset(vist,0,sizeof(vist));
        for(int i=1;i<n; i++)//从最小生成树中去掉一个边,变成两个连通子图,再加入一个边使之连通,加入的长度一定大于等于去掉的边,所以加入的边徐福修。
        {
            vist[edg[i].v]=1;
            int t1=DFS(edg[i].u,0);
            vist[edg[i].u]=1;
            int t2=DFS(edg[i].v,0);
            vist[edg[i].u]=0;
            if((t1+t2)/(sum-map[edg[i].u][edg[i].v])>R)
                R=(t1+t2)/(sum-map[edg[i].u][edg[i].v]);
        }
        printf("%.2lf\n",R);
    }
}

HDU4081Qin Shi Huang's National Road System(最小生成树+DFS)

时间: 2024-10-01 02:34:18

HDU4081Qin Shi Huang's National Road System(最小生成树+DFS)的相关文章

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

//给出每点的坐标和其到人口量,找一个生成树,其中有一条边造价为0 //问A/B的最大值,A这条边连接的两个点的人口之和 //B除了这条边以外的其他边的长度之和 //先找到最小生成树,然后枚举所有边,如果这条边是最小生成树上的边, //直接计算A/(sum-edge) ,如果不是,那么这条边加在最小生成树上会出现一个 //环,去除这个环中的最长的边依然是一棵树, //用dp[u][v] 表示在最小生成树中从u到v的唯一路径所经过的最长边的大小 //dp[u][v[i]] = dp[v[i]][u

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

分析:http://www.cnblogs.com/wally/archive/2013/02/04/2892194.html 这个题就是多一个限制,就是求包含每条边的最小生成树,这个求出原始最小生成树然后查询就好了 然后预处理那个数组是O(n^2)的,这样总时间复杂度是O(n^2+m) 这是因为这个题n比较小,如果n大的时候,就需要路径查询了,比如LCA 或者树链剖分达到O(mlogn) #include <iostream> #include <algorithm> #incl

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(最小生成树+暴力枚举边)

题目大意:给你1000个点,每个点上有一个数目代表这个城市有多少人,让你把这N个点构成一颗生成树,你可以删除其中的任意一条边.让你求出一个比例A/B是的这个比例最大,A表示你删除那条边上两个城市的人口数之和,B表示的是去掉这条变这可生成树上其他的边的总长度. 解体思路:先求出来最小生成树,然后暴力枚举生成树的边,B=总数-这条边的长度.A = 将这条连断开之后左右集合中权值最大的两个数的和. 这样保证了B最小的情况下,去找最大的A,所以是可行的解.生成树的同时建边,然后dfs找最大值. PS:这

HDU 4081 Qin Shi Huang&#39;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 Problem Description

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

同样是看别人题解才明白的 题目大意—— 话说秦始皇统一六国之后,打算修路.他要用n-1条路,将n个城市连接起来,并且使这n-1条路的距离之和最短.最小生成树是不是?不对,还有呢.接着,一个自称徐福的游方道士突然出现,他说他可以不消耗任何人力财力,使用法术凭空造一条路,路的长度无所谓,但是只能造一条.那么问题来了,徐福希望将两座人口数最多的城市连接起来,而秦始皇希望将最长的路修好.最后折中了一下, 将A/B最大的一条路用法术修出来.其中A是两座城市的人口和,B是除了用法术修的路以外,其它需要修建的

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 (传

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