博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
生成树相关问题
阅读量:4662 次
发布时间:2019-06-09

本文共 1618 字,大约阅读时间需要 5 分钟。

算法竞赛入门经典训练指南

第5章 图论算法与模型

5.4 生成树相关问题

例题21 bond UVa11354

有n座城市通过m条双向道路相连,每条道路有一个危险系数。你的任务是回答若干个询问,每个询问包含一个起点s和一个终点t,要求找到一条s到t的路,使得路径所有边的最大危险系数最小。

相似的题

noip 2013 day1 truck

【分析】本题也是要求瓶颈路,但需要快速回答很多查询。这很像前面数据结构部分的题目,因此也可考虑先做预处理,把信息组织成某种易于查询的结构。

首先求出最小生成树,并把它改写成有根树,让fa[i]和cost[i]分别节点i的父亲编号和它与父亲之间的边权,L[i]表示节点i的深度(根节点的深度为0,根节点的子节点深度为1,以此类推)。

无根树转有根树的代码如下。

1 class SetRoot{ 2 public: 3     static void pretreat(vector
& T,vector
* G){ 4 for(int i=0;i
& T,vector
* G,int * fa,int u,int fthr){10 vector
& g=G[u];11 for(int i=0;i

 

接下来通过预处理计算出anc数组和maxcost数组,其中anc[i][j]表示节点i的第2级祖先编号(anc[i][0]就是fa[i],anc[i][j]=-1表示该祖先不存在),maxcost[i][j]表示节点i和它的2j级祖先之间路径上的最大值。预处理代码如下。

1 void prepoccess(){ 2     for(int i=0;i

 有了这些预处理我们就可以编写查询处理过程了。假定查询的两个节点为p和q,并且p比q深(如果不是的话,交换),则可以先把p提升到和q同一级的位置,然后用类似二进制展开的方法不断把p和q同时往上“提”(要保证二者深度始终相等),同时更新最大边权。代码如下。

int query(int p,int q){    int tmp;int log=0;if(L[p]
=0;i--) if(L[p]-(1<
=L[q]){ ans=max(ans,maxcost[p][i]); p=anc[p][i]; } if(p==q)return ans;//LCA(p,q)=p for(int i=log;i>=0;i--) if(anc[p][i]!=-1&&anc[p][i]!=anc[q][i]){ ans=max(ans,maxcost[p][i]); p=anc[p][i]; ans=max(ans,maxcost[q][i]); q=anc[q][i]; } ans=max(ans,cost[p]); ans=max(ans,cost[q]); return ans;//LCA(p,q)=fa[p]=fa[q];}

 上述代码也能求出p和q的最近公共祖先(见注释)。这样,就在预处理O(nlogn),和查询O(logn)的时间内解决了本题。

转载于:https://www.cnblogs.com/JebediahKerman/p/5678625.html

你可能感兴趣的文章
Aliyun cdn访问日志下载
查看>>
[zz]Fedora 15 安装与配置一览
查看>>
有关委托的理解
查看>>
Yii2.0实用功能技巧解密之——分页功能
查看>>
开始撸凝聚普及赛咯
查看>>
thinkphp5 通用后台
查看>>
[转]Show parameter & Table Not exists
查看>>
Vue-router入门
查看>>
setTimeout与setInterval
查看>>
【转】C#详解值类型和引用类型区别
查看>>
(算法)游戏必胜策略
查看>>
SSH免密码登录快速配置方法
查看>>
矩形嵌套
查看>>
JQ图片文件上传之前预览功能
查看>>
二叉树
查看>>
iOS键盘 样式/风格
查看>>
机器学习面试常见问题
查看>>
centos7 源码编译安装最新版apache
查看>>
freemarker(ftl文件)中判断Map<String, Map<String, Integer>>类型中是否包含某个键值(key)...
查看>>
函数指针
查看>>