您的位置:首页 > 其它

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


题目給的稠密图,怕超时只得放弃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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: