题意:

  秦始皇要在n个城市之间修路,而徐福声可以用法术位秦始皇免费修1条路,每个城市还有人口数,现要求徐福声所修之路的两城市的人口数之和A尽量大,而使n个城市互通需要修的路长B尽量短,从而使得A/B最大。问A/B最大是多少?(1000个城市)

思路:

  老徐可免费修得1条路,那么剩下最多也只需要修n-2条路了,这n-2条路要尽量挑短的,而老徐的那条无所谓长短,只要两城人口尽量多即可。这是没有什么贪心策略的,因为老徐所修之路会影响MST的权值之和的大小。穷举所有城市对要O(n*n),再求次MST需要O(n*n),不可行。

  换个思路,如果能先求得MST,然后穷举要老徐所要修的路,那么在加上老徐的路之后,必然会有个环的出现,这个环中有一条边是不需要的,当然不是老徐那条。这只需要在原MST中求这个环的最小瓶颈路就行了,将其删掉,加上老徐的路,构成新的MST了,进行求值。穷举老徐所要修的路也要O(n*n),那么求瓶颈路就只能用O(1)了。这可以预处理出任意城市对之间的最小瓶颈路,O(n*n)而已。

  任意点对的最小瓶颈路的求法:对原图求最小生成树,只留下树边,树中任意点对之间的路径就是该点对的最小瓶颈路。接着对树图进行DFS,在DFS过程中,顺便求出任意点对的最小瓶颈路,考虑求当前节点x到其他点的最小瓶颈路,设其父亲far,那么x可以通过far到达前面已经访问过的节点,为maxcost[已访问过的节点][far]与cost[far][x]其中的大者。按此思路,在DFS过程中可以求出任意点对的最小瓶颈路。

 #include <bits/stdc++.h>
#include <cstdio>
#include <vector>
#include <iostream>
#include <algorithm>
#define INF 0x7f7f7f7f
#define pii pair<int,int>
#define LL long long
using namespace std;
const int N=;
int a[N], b[N], seq[N]; //求MST用的
int x[N], y[N], p[N]; //所给的坐标及人口数
int pre[N], vis[N], used[N]; //求任意点对最小瓶颈路用的
double w[N], maxcost[][]; //两点间的最小瓶颈maxcost
vector<int> vect[N]; //建树时用
vector<int> dfn; //记录访问过的节点 int cmp(int a,int b){return w[a]<w[b];}
int find(int x){return pre[x]==x? x: pre[x]=find(pre[x]);} //并查集
double dis(int a,int b){return sqrt((x[a]-x[b])*(x[a]-x[b])+(y[a]-y[b])*(y[a]-y[b]));} void DFS(int x)
{
dfn.push_back(x); //访问过
vis[x]=;
for(int i=; i<vect[x].size(); i++)
{
int t=vect[x][i];
if(!vis[t] )
{
for(int j=; j<dfn.size(); j++) //对于所有已经访问过的节点
{
int from=dfn[j];
maxcost[t][from]=maxcost[from][t]=max(maxcost[from][x], dis(x, t) );//通过x连到t
}
DFS(t);
}
}
} void init(int n) //一堆初始化。
{
dfn.clear();
for(int i=; i<=n; i++) vect[i].clear(),pre[i]=i;
for(int i=; i<=n; i++)
for(int j=; j<=n; j++)
maxcost[i][j]=0.0;
memset(used, , sizeof(used));
memset(vis, , sizeof(vis));
}
double cal(int n, int m)
{
init(n);
double sum=0.0; //MST
for(int i=; i<m; i++) //kruscal求最小生成树
{
int u=find(a[seq[i]]);
int v=find(b[seq[i]]);
if( u!=v )
{
pre[u]=v; //不是同个连通块,则连接。
vect[a[seq[i]]].push_back( b[seq[i]] ); //顺便建图,方便建树
vect[b[seq[i]]].push_back( a[seq[i]] );
used[seq[i]]=;
sum+=w[seq[i]];
}
} DFS(); //求任意点对间的最小瓶颈路
double ans=0.0;
for(int i=; i<m; i++) //穷举徐福声将要建的边。
{
double A=p[a[i]]+p[b[i]], B; if(used[i]) B=sum-w[i]; //树上的边
else B=sum-maxcost[a[i]][b[i]];
ans=max( A/B, ans );
}
return ans;
} int main()
{
freopen("input.txt", "r", stdin);
int t, n;
cin>>t;
while(t--)
{
cin>>n;
for(int i=; i<=n; i++) scanf("%d%d%d",&x[i],&y[i],&p[i]);
int cnt=;
for(int i=; i<=n; i++) //求两点间的距离,共n*(n-1)/2条边
{
for(int j=i+; j<=n; j++)
{
a[cnt]=i;
b[cnt]=j;
w[cnt]=dis(i,j);
seq[cnt]=cnt; //千万不要用seq[cnt]=cnt++;或者seq[cnt++]=cnt。
cnt++;
}
}
sort(seq, seq+cnt, cmp); //按边长排序
printf("%.2f\n", cal(n, cnt));
} return ;
}

AC代码

UVALive 5713 Qin Shi Huang's National Road System秦始皇修路(MST,最小瓶颈路)的更多相关文章

  1. UValive 5713 Qin Shi Huang's National Road System

    Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3 ...

  2. UVALive 5713 Qin Shi Huang's National Road System(次小生成树)

    题意:对于已知的网络构建道路,使城市两两之间能够互相到达.其中一条道路是可以免费修建的,问需要修建的总长度B与免费修建的道路所连接的两城市的人口之和A的比值A/B最大是多少. 因为是求A/B的最大值, ...

  3. LA 5713 - Qin Shi Huang's National Road System(HDU 4081) MST

    LA:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_pr ...

  4. 【最小生成树】UVA1494Qin Shi Huang's National Road System秦始皇修路

    Description During the Warring States Period of ancient China(476 BC to 221 BC), there were seven ki ...

  5. uvalive 5731 Qin Shi Huang’s National Road System

    题意: 秦始皇要修路使得所有的城市连起来,并且花费最少:有一个人,叫徐福,他可以修一条魔法路,不花费任何的钱与劳动力. 秦始皇想让修路的费用最少,但是徐福想要受益的人最多,所以他们经过协商,决定让 A ...

  6. hdu 4081 Qin Shi Huang's National Road System (次小生成树)

    Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3 ...

  7. hdu 4081 Qin Shi Huang's National Road System (次小生成树的变形)

    题目:Qin Shi Huang's National Road System Qin Shi Huang's National Road System Time Limit: 2000/1000 M ...

  8. HDU 4081 Qin Shi Huang's National Road System 次小生成树变种

    Qin Shi Huang's National Road System Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/3 ...

  9. Qin Shi Huang's National Road System HDU - 4081(树形dp+最小生成树)

    Qin Shi Huang's National Road System HDU - 4081 感觉这道题和hdu4756很像... 求最小生成树里面删去一边E1 再加一边E2 求该边两顶点权值和除以 ...

随机推荐

  1. codeforces 430A Points and Segments (easy)(理解能力有待提高……)

    题目 //终于看懂题目了,,,, //一条线段里面不是每个坐标上都有要染色的点,所以为了满足条件,只能考虑那些给出坐标的点 //所以就要排序一下了,不能直接根据坐标0 1 0 1…… #include ...

  2. 同一网站不同和二级域名和不同子目录的cookie

    1.cookie二级域名的实现: 用户其中一个站点登录,而且可以各个子频道间切换,保持登录状态设置Cookie时,使用如下代码即可:setcookie(name,value,expire,path,& ...

  3. Services学习(一)

    对于需要长期运行,例如播放音乐.长期和服务器的连接,即使已不是屏幕当前的activity仍需要运行的情况,采用服务方式.服务将通过API触发启动或者通过IPC(Interprocess Communi ...

  4. ThinkPHP 单字母函数整理

    TP所有单独的函数,除了两个用来生成项目的buildAppDir之类的,其余都在框架目录/Common/functions.php这个文件里. A函数(基本是Action的简写) A函数是用来实例化我 ...

  5. Ms sql server sql优化技巧

    SET STATISTICS PROFILE ON SET STATISTICS IO ON SET STATISTICS TIME ON SELECT * FROM userinfo WHERE N ...

  6. C# 中Newtonsoft.Json的安装和使用

    官网参考:http://json.codeplex.com/ 在程序包管理控制台,键入NuGet命令  install-package Newtonsoft.Json  安装Newtonsoft.Js ...

  7. WCF分布式开发步步为赢(10):请求应答(Request-Reply)、单向操作(One-Way)、回调操作(Call Back).

    WCF除了支持经典的请求应答(Request-Reply)模式外,还提供了什么操作调用模式,他们有什么不同以及我们如何在开发中使用这些操作调用模式.今天本节文章里会详细介绍.WCF分布式开发步步为赢( ...

  8. C Primer Plus之位操作

       二进制补码表示法 几乎所有的计算机都使用二进制补码表示法来存储位于n位存储单元中的有符号整数.    在二进制补码表示法中,最左位决定符号.如果它是0,该整数为正(即非负):如果是1,该整数为负 ...

  9. jmeter 302请求测试

    需求,测试url:  http://test.123.com/123.action,请求该url之后会进行302跳转,判断跳转的页面是不是http://www.haha.com. 这个其实本质还是普通 ...

  10. 纯CSS实现的右侧底部简洁悬浮效果

    我们见过很多页面右侧浮动效果,最早有QQ联系面板,对联广告等,大多数都是基于Javascript实现的动态效果,今天我给大家分享一个只需要CSS结合DIV实现的右侧浮动效果. HTML 我们希望悬浮效 ...