HDU-4081 Qin Shi Huang's National Road System(最小生成树[Prim])
2015-08-20 20:45
197 查看
Qin Shi Huang's National Road System
Time Limit : 2000/1000ms (Java/Other) Memory Limit : 32768/32768K (Java/Other)
Problem Description
During the Warring States Period of ancient China(476 BC to 221 BC), there were sevenkingdoms 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. Theresult 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
题目給的稠密图,怕超时只得放弃Kruskal算法。
第一反应是贪心,直接在人口最多的两座城市建立magic rode,仔细一想明显会错,A虽然取得最大,但是B也可能会大。
然后就想到枚举任意两点的边为magic rode,求最小生成树,但这样又会超时。
最后看到大家都是先求最小生成树,再枚举每条边去掉,然后在两部分分别找人口最大的城市添上magic rode即可
#include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; struct Edge { int s,e; double d; }tr[1005];//tr[i]表示第i次加入最小生成树的边 const double INF=99999999; const double EPS=0.000001; int n,x[1005],y[1005],p[1005],near[1005],u,maxp; double g[1005][1005],dis[1005],tmp,ans,sum; bool vis[1005]; vector<int> adj[1005];//adj[i]表示最小生成树中与i有边的点集 void Prim() { int i,j; dis[0]=INF,dis[1]=sum=0; near[1]=1;//near[i]表示i点距离最小生成树的near[i]点最近 for(i=0;i<n;++i) { u=0; for(j=1;j<=n;++j) if(!vis[j]&&dis[j]+EPS<dis[u]) u=j; vis[u]=true; sum+=(tr[i].d=dis[u]); adj[tr[i].s=u].push_back(near[u]); adj[tr[i].e=near[u]].push_back(u); for(j=1;j<=n;++j) { if(dis[j]-EPS>g[u][j]) { dis[j]=g[u][j]; near[j]=u; } } } } void dfs(int s) {//深搜所有在s这边的点 vis[s]=true; maxp=max(maxp,p[s]); for(int i=0;i<adj[s].size();++i) if(!vis[adj[s][i]]) dfs(adj[s][i]); } int main() { int i,j,T,dx,dy; scanf("%d",&T); while(T--) { scanf("%d",&n); for(i=1;i<=n;++i) { scanf("%d%d%d",x+i,y+i,p+i); for(j=1;j<i;++j) { dx=x[i]-x[j],dy=y[i]-y[j]; g[i][j]=g[j][i]=sqrt(double(dx*dx+dy*dy)); } vis[i]=false,dis[i]=INF; adj[i].clear(); } adj[0].clear(); Prim(); ans=0; for(i=1;i<n;++i) { tmp=maxp=0; memset(vis,false,sizeof(vis)); vis[tr[i].s]=true;//将tr[i].e到tr[i].s这条边删除 dfs(tr[i].e);//统计tr[i].e这边所有点最大人口数 tmp+=maxp; maxp=0; memset(vis,false,sizeof(vis)); vis[tr[i].e]=true;//将tr[i].s到tr[i].e这条边删除 dfs(tr[i].s);//统计tr[i].s这边所有点最大人口数 tmp+=maxp; tmp/=(sum-tr[i].d); if(ans+EPS<tmp) ans=tmp; } printf("%.2lf\n",ans); } return 0; }
相关文章推荐
- twistd一行服务器的方法,搭建DNS、Web文件服务器
- 面向对象与面向过程的编程思想比较
- C++ Primer 5e chapter 7
- codves:最小生成树
- unix network programming(3rd)Vol.1 [第13~15章]《读书笔记系列》
- ubuntu 1204 无法安装libmysqlclient-dev
- 有return的情况下try catch finally的执行顺序(最有说服力的总结)
- Python实例浅谈之三Python与C/C++相互调用
- 开源ffmpeg项目记录
- 144. Binary Tree Preorder Traversal
- 集合的遍历
- swift 百度地图开发问题
- ADT升级到23出错,卸载旧版本ADT时出错Cannot complete the install because of a conflicting dependency.
- POJ 2528 线段树+离散化(水水的线段树+略复杂的离散化)
- 第五章 引用类型
- HDU-1166敌兵布阵
- autolayout - sizeClass - Masonry - 6
- codeforces 559A(Gerald's Hexagon)
- PAT 1010. Radix (25)
- Java中的内存泄露