HDU 4081秦皇修路(次小生成树)

标签: 次小生成树
3人阅读 评论(0) 收藏 举报
分类:

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.

Ouput

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

关于题解推荐一篇博客博客链接,这篇博客已经讲得很透彻了。

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<memory.h>
#include<cmath>
#define M 1010
#define inf 99999999999.0
using namespace std;
double g[M][M],path[M][M];
//注意存在小数所以改成double
double dist[M],cost[M];
//cost为每个城市的人口
int pre[M],vis[M],r[M][2];
//用数组r来保存每个城市的坐标,然后通过距离公式求出距离存在图g中
bool used[M][M];//最小树的标记数组
int n,m;
double mst;
void init(){//初始化
    for(int i=1;i<=n;i++){
        for(int j=i+1;j<=n;j++){
            g[i][j]=g[j][i]=inf;
        }
    }
    return;
}
void Found(){//距离公式计算出每条边的边长
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            g[i][j]=g[j][i]=sqrt((r[i][0]-r[j][0])*(r[i][0]-r[j][0])+(r[i][1]-r[j][1])*(r[i][1]-r[j][1]));
        }
    }
}
double prime(){
    double mst=0.0;//最小生成树的值
    memset(path,0,sizeof(path));
    memset(vis,0,sizeof(vis));
    memset(used,0,sizeof(used));
    vis[1]=1;
    for(int i=1;i<=n;i++){
        dist[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(!vis[j]){
                if(u==-1||dist[j]<dist[u]){
                    u=j;
                }
            }
        }
        used[u][pre[u]]=used[pre[u]][u]=true;//确定此边已经使用过了
        mst+=g[pre[u]][u];
        vis[u]=1;
        for(int j=1;j<=n;j++){
            if(vis[j]&&j!=u){//path记录了已经加入最小生成树的点到u的最长路
                path[j][u]=path[u][j]=max(path[j][pre[u]],dist[u]);
            }
            if(!vis[j]){
                if(dist[j]>g[u][j]){//松弛
                    dist[j]=g[u][j];
                    pre[j]=u;
                }
            }
        }
    }
    return mst;
}
double second_tree(){
    double res=inf;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i!=j&&!used[i][j]){//次小生成树
                res=min(res,mst-path[i][j]+g[i][j]);
            }
        }
    }
    return res;
}
int main(){
    int t;
    int x,y,z;
    cin>>t;
    while(t--){
        cin>>n;
        m=((n-1)*n)/2;
        init();
        memset(r,0,sizeof(r));
        memset(cost,0,sizeof(cost));
        for(int i=1;i<=n;i++){
            scanf("%d%d%lf",&r[i][0],&r[i][1],&cost[i]);
        }
        Found();
        mst=prime();
        double sec_mst=second_tree();
        double ratios= -1.0;
        for(int i=1; i<=n; ++i){
            for(int j=1; j<=n; ++j)if(i!=j){
                if(used[i][j]){
                    ratios=max(ratios, (cost[i]+cost[j])/(mst-g[i][j]));
                }
                else{
                    ratios=max(ratios, (cost[i]+cost[j])/(mst-path[i][j]));
                }
            }
        }
        printf("%.2f\n", ratios);
    }
    return 0;
}
查看评论

hdu4081(次小生成树) Qin Shi Huang's National Road System

下面让我们来分析一下这个题 秦始皇统一中国之后要在全国修公路连接各个城市,抠门皇帝只想修成最小生成树(距离最小,不考虑人力),一个道士说自己可以不花人力物力修一条路,经过两方妥协,选择max(两个城...
  • zcmartin2014214283
  • zcmartin2014214283
  • 2016-03-25 13:41:10
  • 998

HDU 4081 秦始皇修路 次小生成树

注意精度问题,不要用强转。   #include #include #include #include #include #include #define N 1010 ...
  • qq574857122
  • qq574857122
  • 2014-01-18 22:16:22
  • 1420

Kruskal,次小生成树,最小瓶颈路(秦始皇修路,LA 5713)

#include #define rep(i,a,b) for(int i=a;i
  • xl2015190026
  • xl2015190026
  • 2017-02-12 15:03:49
  • 270

HDU 4081 次小生成树变形记

点击打开链接 题意:n个点用n-1条边连起来,问两个点的人口A除以总的距离减去这两点的距离的最大值,表达能力有限,看看别人怎么翻译的吧,但是代码还是不错的...... 思路:用到的是次小生成树中的...
  • Dan__ge
  • Dan__ge
  • 2016-03-22 19:56:32
  • 544

HDU 4081 秦始皇修路

http://acm.hdu.edu.cn/showproblem.php?pid=4081 有n坐城市,输入每坐城市的坐标和人口。 现在要在所有城市之间修路,保证每个城市都能相连,并且保证A/B...
  • YDYKL
  • YDYKL
  • 2011-11-04 20:05:00
  • 1264

hdu 4081 次小生成树

http://acm.hdu.edu.cn/showproblem.php?pid=4081 我就不说题意了,为了使A/B最大,就应该是B越小,故可以先求出n个点的最小生成树。因此,可以枚举每一条边...
  • zjsyhjh
  • zjsyhjh
  • 2014-05-26 17:51:43
  • 231

HDU 4081 Qin Shi Huang's National Road System (次小生成树算法)

链接: http://acm.hdu.edu.cn/showproblem.php?pid=4081 题目: Problem Description During th...
  • shuangde800
  • shuangde800
  • 2012-09-16 00:42:58
  • 4495

HDU 4081 次小生成树模板

Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3...
  • xjh_shin
  • xjh_shin
  • 2017-06-03 09:03:36
  • 170

HDU 4081(次小生成树)

次小生成树模板题 #include #include #include #include #define maxn 1002 #define maxm (maxn * maxn) >> 1 ...
  • u013615904
  • u013615904
  • 2015-08-25 16:10:23
  • 158

HDU 4081 次小生成树模板题

先求最小生成树,然后对于最小生成树这个图中的所有点对,求出任意两点之间的所有路径上的最大边,注意是对于构造出来的最小生成树这个图来说。 然后枚举删每一条边,求最优解。 #include ...
  • THE___BEST
  • THE___BEST
  • 2016-04-08 21:18:37
  • 157
    个人资料
    持之以恒
    等级:
    访问量: 602
    积分: 294
    排名: 26万+
    文章存档
    最新评论