【问题描述】
 
  秦朝有N个城市,需要修建一些道路使得任意两个城市之间都可以相互连通。道士徐福生称他可以用法术修路,不花钱,也不用劳动力,但只能修一条,因此需要慎重选择用法术修建哪一条路。

  秦始皇不仅希望他道路总长度B尽量短(这样可以节省劳力),还希望法术连接的两个城市人口之和A尽量大,因此下令寻找一个使A/B最大的方案。你的任务就是找到这个方案。

  注意,并不是任意两个城市都可以修建道路,这个信息在输入中给出。 
 
【输入格式】
 
  第一行为整数:N,M,分别表示城市数量(编号为1..N)和可选修的道路数量;
  接下来的一行包含N个整数,第i个整数表示城市i的人口数量。
  接下来的M行,每行3个整数x,y,cost,表示城市x和城市y之间可以修建一条路,修这条路的花费为cost。
 
【输出格式】
 
  输出A/B的最大值,四舍五入保留4位小数。
 
【输入样例】
 
6 8
8 7 3 5 9 6
1 2 4
2 3 3
2 4 2
1 5 1
5 6 3
3 5 4
6 2 5
1 6 4

【输出样例】
 
1.6667 
 
【数据范围】
 
3<=N<=100000
N<=M<=300000

每个城市的人口数量不超过:2 000 000 000

cqyz的题库这题有点不同,《算法竞赛训练指南》上的题目是多组数据,每组都比较小;到了这改了一下,一组数据,规模很大....无非是顺便练一下LCA

分析:

1.题目大意:让你选一些边,把整个图连通,然后从中选一条边,这边连接的两个点的人口和为分子,总路径长度减去这条路做分母,然后求分子除以分母最大是多少;注意,此处只要这个比值最大,不要求路径最短或者人最多;

2.要让这个比值尽量大,分子是人口不好操作,分母要尽量小却可行,也就是边的长度和要尽量小,便自然想到最小生成树;

3.生成最小生成树之后,接下来只需要枚举每条边(包括生成树里和不在生成树里的),设u,v为这条边连接的两个点,求出最小生成树上两点间的最大边,用这两个点的人口和/(总路径长度-这条最大边的长度),答案取最大值即可。

4.如何实现???套用LCA模板,利用2进制,维护maxE和fa数组。这个不会的话需要巩固一下LCA。

细节:

1.为什么求出两点间最大边是对的?

枚举到一条边(u,v)时,最小生成树中u,v已径连通,如果加入这条边就形成圈。因为这条加入的边是免费的,所以相当于这条边的长度为0,可以扔掉原来圈里的的一条边,u,v和其他点仍然连通。因为u,v点的人口是确定的,所以要找一条最大的边扔掉使得比值最大。

2.为什么所有的边都要枚举,而不是只枚举生成树里的或不在生成树里的?

此题和原题不同,原题两个点间可任意连接,于是直接枚举点与点的最大边,两个for即可。

注意读题,此题只能连接给定的边。此处枚举边,实质是在枚举点,只不过是在枚举可以直接连接的点对,因为不像原题任意两个点都可以连,所以下面的代码可以看见枚举边时,枚举到的这条边长度根本没有用到。之所以所有边都枚举就是不放过一个可以连的点对。

注:Ufs_表示这是并查集用的,Tree_表示这是生成树上用的。

#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;typedef long long LL;
typedef double DB;
const LL maxn=100005;
const LL maxm=300005;LL n,m,np=0,MAXDEP,people[maxn],last[maxn],Tree_fa[maxn][20],Tree_maxE[maxn][20],Tree_dep[maxn],two[25];
LL Ufs_fa[maxn],Ufs_vis[maxm];struct data{LL u,v,w;}Ufs_E[maxm];
struct edge{LL to,w,pre;}Tree_E[maxn*2];//生成树总共n-1条边 inline bool cmp(data a,data b) {return a.w<b.w;}char c;
inline void qkscanf(LL &x)
{for(c=getchar();c<'0'||c>'9';c=getchar());for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
}inline void addedge(LL u,LL v,LL w)
{Tree_E[++np]=(edge){v,w,last[u]};last[u]=np;
}inline LL Find(LL x) {return Ufs_fa[x]==x?x:Ufs_fa[x]=Find(Ufs_fa[x]);}inline void Merge(LL x,LL y) {Ufs_fa[Find(x)]=Find(y);}LL Kruscal()
{sort(Ufs_E+1,Ufs_E+1+m,cmp);for(LL i=1;i<=n;i++) Ufs_fa[i]=i;LL sum=0;LL cnt=0,u,v,w;for(LL i=1;i<=m;i++){u=Ufs_E[i].u,v=Ufs_E[i].v,w=Ufs_E[i].w;if(Find(u)==Find(v)) continue;sum+=w;Merge(u,v);Ufs_vis[i]=1;cnt++;addedge(u,v,w);//加入最小生成树 addedge(v,u,w);if(cnt==n-1) break;}return sum;
}inline void DFS(LL i,LL fa,LL maxE_now,LL dep)
{Tree_dep[i]=dep;Tree_fa[i][0]=fa;Tree_maxE[i][0]=maxE_now;for(LL p=1;p<=MAXDEP;p++){LL j=Tree_fa[i][p-1];Tree_fa[i][p]=Tree_fa[j][p-1];Tree_maxE[i][p]=max(Tree_maxE[i][p-1],Tree_maxE[j][p-1]); }for(LL p=last[i];p;p=Tree_E[p].pre){LL j=Tree_E[p].to;if(j==fa) continue;DFS(j,i,Tree_E[p].w,dep+1);}
}inline LL LCA(LL u,LL v)
{if(Tree_dep[u]<Tree_dep[v]) swap(u,v);LL x=Tree_dep[u]-Tree_dep[v];for(LL i=MAXDEP;i>=0;i--) if(x&two[i]) u=Tree_fa[u][i];if(u==v) return u;for(LL i=MAXDEP;i>=0;i--) if(Tree_fa[u][i]!=Tree_fa[v][i]){u=Tree_fa[u][i];v=Tree_fa[v][i];}return Tree_fa[u][0];
}inline LL ques(LL u,LL lca)
{LL ans=-1;for(LL i=MAXDEP;i>=0;i--){if(Tree_dep[Tree_fa[u][i]]>=Tree_dep[lca]){ans=max(ans,Tree_maxE[u][i]);u=Tree_fa[u][i];}}return ans;
}int main()
{
//  freopen("in.txt","r",stdin);//inputqkscanf(n);qkscanf(m);LL u,v,w;for(LL i=1;i<=n;i++) qkscanf(people[i]);for(LL i=1;i<=m;i++){qkscanf(u);qkscanf(v);qkscanf(w);Ufs_E[i]=(data){u,v,w};}//form a treeLL sum=Kruscal();LL i=0,k=1;while(k<n*3) two[i++]=k,k*=2;//2的次方,便于调用 MAXDEP=i;//最大深度,枚举2的次方时用到 DFS(1,0,0,1);//生成树上的信息 //solve questionDB ans=-1;for(LL i=1;i<=m;i++){u=Ufs_E[i].u,v=Ufs_E[i].v;//   并没有用到这条边的长度!!!! LL lca=LCA(u,v);LL MAXE=max(ques(u,lca),ques(v,lca));DB t=(DB)(people[u]+people[v])/(DB)(sum-MAXE);ans=max(ans,t);}//outputprintf("%.4llf",ans);return 0;
}

秦始皇修路(最小生成树+LCA)相关推荐

  1. LA 5713 秦始皇修路

    https://vjudge.net/problem/UVALive-5713 题意: 秦朝有n个城市,需要修建一些道路使得任意两个城市之间都可以连通.道士徐福声称他可以用法术修路,不花钱,也不用劳动 ...

  2. 【最小生成树+LCA】Imperial roads

    http://codeforces.com/gym/101889 I 先跑一遍最小生成树,把经过的边和答案记录下来 对于每个询问的边,显然如果处于MST中,答案不变 如果不在MST中,假设这条边连上了 ...

  3. 51nod1743-雪之国度【最小生成树,LCA,并查集】

    正题 题目链接:http://www.51nod.com/Challenge/Problem.html#problemId=1743 题目大意 nnn个点mmm条边的一张图,每次询问要求找出x,yx, ...

  4. codevs1519 过路费(最小生成树+LCA)

    1519 过路费  时间限制: 1 s  空间限制: 256000 KB  题目等级 : 大师 Master 题目描述 Description 在某个遥远的国家里,有 n个城市.编号为 1,2,3,- ...

  5. 例题5.20 秦始皇修路 LA5713

    1.题目描述:点击打开链接 2.解题思路:本题利用次小生成树解决.根据题意,我们希望在O(1)时间内得知"在原图中删除边u-v后的最小生成树的权值",这样,整个问题就可以在O(n^ ...

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

  7. NOIP 2013 day1

    tags: 模拟 快速幂 逆序对 树状数组 归并排序 最小生成树 lca 倍增 categories: 信息学竞赛 总结 tex live 2017.iso 转圈游戏 火柴排队 货车运输 转圈游戏 s ...

  8. 【NOIP2013提高组day1】货车运输

    额呵呵,找到一个照片开始乱搞ing.(嘻嘻 car-driver 前奏 题目大意 题目解法 最小生成树 LCA 前奏 让我们进入正题,这道题目所涉知识面是很广的. 先来列举一下这道题的知识点:最小生成 ...

  9. 2018ICPC徐州赛区网络预赛

    今天打了这个比赛,水题挺多~(体验很好(太菜了)) 传送门:https://www.jisuanke.com/contest/1557?view=challenges ~ A. Hard to pre ...

最新文章

  1. 【dotnet跨平台】Visual Studio Code常见问答
  2. centOS 7 yum安装MySQL5.6
  3. 计算机网络原理和OSI模型与TCP模型
  4. mysql操作常见问题_MySQL:常见使用问题
  5. Java类之File记录
  6. 12.8 早晨我一直在假笑,为了骗自己
  7. 将Amazon Cognito与单页面应用程序(Vue.js)集成
  8. mac下 如果docker 如果访问不到网 就下载哥docker-machine 然后进入到vbox下进行操作
  9. 如何创建_如何创建自己的微信圈子?圈子创建运营指南
  10. Docker 安装Node-Exporter+ Prometheus Server +Grafana
  11. 计算机组成与体系结构——计算机结构——2020.11.19
  12. matlab调用库函数,Matlab调用函数的详细操作
  13. 解决vm安装过程显示无人参与应答文件包含的产品密钥无效
  14. RecyclerView+Retrofit+OkHttp+RxJava
  15. 帆软(FineReport)主子报表(报表联动)
  16. 优化LNMP架构采用“Website Baker”为小型公司创建高性能网站方案
  17. vs code php终端输出中文乱码及环境配置解决办法
  18. 睡眠手环APP开发上线
  19. Minecraft Server 搭建手账
  20. 计算机网络上有个红叉没无线,电脑连接不可用红叉,有无线网络但无法连接上wifi...

热门文章

  1. 艾永亮:服装业的投机主义,满足的到底是谁的需求?
  2. 2020之后IT技术的应用思考
  3. uCOS2源码分析1-BSP部分-第4季第2部分视频课程-朱有鹏-专题视频课程
  4. 【Linux】入门介绍
  5. 双通道连续波多普勒雷达测速模型 - Matlab仿真
  6. 这个“安装 OS X Yosemite”应用程序副本不能验证
  7. 孪生素数【函数实现】
  8. PTA题目 抓老鼠啊~亏了还是赚了?
  9. 给计算机老师发一封信,写给计算机老师的感谢信.doc
  10. 为什么我要在BDTC2016上担任“大数据云服务”分论坛召集人