在某个遥远的国家里,有 n个城市。编号为 1,2,3,…,n。这个国家的政府修建了m 条双向道路,每条道路连接着两个城市。政府规定从城市 S 到城市T需要收取的过路费为所经过城市之间道路长度的最大值。如:A到B长度为 2,B到C 长度为3,那么开车从 A经过 B到C 需要上交的过路费为 3。
    佳佳是个做生意的人,需要经常开车从任意一个城市到另外一个城市,因此他需要频繁地上交过路费,由于忙于做生意,所以他无时间来寻找交过路费最低的行驶路线。然而, 当他交的过路费越多他的心情就变得越糟糕。 作为秘书的你,需要每次根据老板的起止城市,提供给他从开始城市到达目的城市,最少需要上交多少过路费。

  这道题的数据范围比较大,n<=10^5,q<=10^4

  所以解决每一个询问的时间不能太大

  我们考虑两点间的路径中边权最大值最小的路径

  突然联想到最小生成树的性质之一:整棵树中最大的边权最小

  和我们的条件有一点相似但也不大一样

  那是否两点间路径中边权最大值最小的路径一定在最小生成树中呢?

  我们先假设不成立,即树上两点u,v之间存在一条路径中的最大值d

  小于生成树上u,v之间路径上的最大值x

  然后考虑最小生成树的Kruskal过程,我们将所有的边边权从小到大加入

  那么显然,如果u,v间的所有边边权都小于x,那么在x加入之前u,v必然已经达到联通状态

  所以这种情况是不可能出现的

  

  所以任意两点间路径中最大边权最小的路径必定在整张图的最小生成树中!

  这一点得证之后,对于每个询问,O(logn)的倍增查找就可以了

program xjt1;
const maxm = ;maxn = ;
var n,m,i,x,y,z,e,q:longint;
ter,next,w:array[-..maxm]of longint;
link,fat,dep:array[-..maxn]of longint;
a:array[-..maxm]of record x,y,z:longint;end;
dis,fa:array[-..maxn,-..]of longint; function max(a,b:longint):longint;
begin
if a>b then exit(a) else exit(b);
end; procedure add(x,y,z:longint);
begin
inc(e);ter[e]:=y;next[e]:=link[x];link[x]:=e;w[e]:=z;
inc(e);ter[e]:=x;next[e]:=link[y];link[y]:=e;w[e]:=z;
end; procedure qsort(L,R:longint);
var i,j,mid:longint;
begin
i:=L;j:=R;mid:=a[random(R-L+)+L].z;
repeat
while (i<R)and(a[i].z<mid) do inc(i);
while (L<j)and(a[j].z>mid) do dec(j);
if i<=j then
begin
a[]:=a[i];a[i]:=a[j];a[j]:=a[];
inc(i);dec(j);
end;
until i>j;
if i<R then qsort(i,R);
if L<j then qsort(L,j);
end; function getfa(x:longint):longint;
begin
if fat[x]=x then exit(x);
fat[x]:=getfa(fat[x]);
exit(fat[x]);
end; procedure dfs(p:longint);
var i,j:longint;
begin
for i:= to do
begin
if dep[p]<= << i then break;
fa[p][i]:=fa[fa[p][i-]][i-];
dis[p][i]:=max(dis[p][i-],dis[fa[p][i-]][i-])
end;
j:=link[p];
while j<> do
begin
if dep[ter[j]]= then
begin
dep[ter[j]]:=dep[p]+;
fa[ter[j]][]:=p;
dis[ter[j]][]:=w[j];
dfs(ter[j]);
end;
j:=next[j];
end;
end; function lca(x,y:longint):longint;
var i,tem:longint;
begin
if x = y then exit();
lca:=;
if dep[x]<dep[y] then
begin
tem:=x;x:=y;y:=tem;
end;
if dep[x]>dep[y] then
begin
i:=trunc(ln(dep[x]-dep[y])/ln());
while dep[x]>dep[y] do
begin
while dep[x]-dep[y]>= << i do
begin
lca:=max(lca,dis[x][i]);
x:=fa[x][i];
end;
dec(i);
end;
end;
if x <> y then
begin
i:=trunc(ln(n)/ln());
while fa[x][]<>fa[y][] do
begin
while fa[x][i]<>fa[y][i] do
begin
lca:=max(max(lca,dis[x][i]),dis[y][i]);
x:=fa[x][i];y:=fa[y][i];
end;
dec(i);
end;
lca:=max(lca,dis[x][]);
lca:=max(lca,dis[y][]);
end;
end; begin
readln(n,m);e:=;
for i:= to m do with a[i] do
begin
readln(x,y,z);
end;
qsort(,m);
for i:= to n do fat[i]:=i;
for i:= to m do
begin
x:=getfa(a[i].x);y:=getfa(a[i].y);
if x<>y then
begin
fat[x]:=y;
// writeln(a[i].z);
add(a[i].x,a[i].y,a[i].z);
end;
end;
dep[]:=;dfs();
readln(q);
for i:= to q do
begin
readln(x,y);
writeln(lca(x,y));
end;
end.

  

[Codevs1519]过路费解题报告|最小生成树|LCA的更多相关文章

  1. 习题:codevs 1519 过路费 解题报告

    今天拿了这道题目练练手,感觉自己代码能力又增强了不少: 我的思路跟别人可能不一样. 首先我们很容易就能看出,我们需要的边就是最小生成树算法kruskal算法求出来的边,其余的边都可以删掉,于是就有了这 ...

  2. [NOIP2015模拟10.22] 最小代价 解题报告 (最小生成树)

    Description 给出一幅由n个点m条边构成的无向带权图.其中有些点是黑点,其他点是白点.现在每个白点都要与他距离最近的黑点通过最短路连接(如果有很多个黑点,可以选取其中任意一个),我们想要使得 ...

  3. 北大ACM试题分类+部分解题报告链接

    转载请注明出处:優YoU http://blog.csdn.net/lyy289065406/article/details/6642573 部分解题报告添加新内容,除了原有的"大致题意&q ...

  4. CH Round #56 - 国庆节欢乐赛解题报告

    最近CH上的比赛很多,在此会全部写出解题报告,与大家交流一下解题方法与技巧. T1 魔幻森林 描述 Cortana来到了一片魔幻森林,这片森林可以被视作一个N*M的矩阵,矩阵中的每个位置上都长着一棵树 ...

  5. 【NOIP2015】提高day2解题报告

    题目: P1981跳石头 描述 一年一度的“跳石头”比赛又要开始了!这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石.组委会已经选择好了两块岩石作为比赛起点和终点.在起点和终点之间,有 N ...

  6. NOIP2015 提高组(senior) 解题报告

    过了这么久才来发解题报告,蒟蒻实在惭愧 /w\ Day1 T1 [思路] 模拟 [代码] #include<iostream> #include<cstring> #inclu ...

  7. $HNOI\ 2010$ 解题报告

    HNOI 2010 解题报告 0. HNOI2010 AC代码包下载地址 注: 戳上面的标题中的'地址' 下载 代码包, 戳下面每一题的文件名 可进入 题目链接. 每一题 对应代码的文件名 我在 每一 ...

  8. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

  9. 【百度之星2014~复赛)解题报告】The Query on the Tree

    声明 笔者最近意外的发现 笔者的个人网站http://tiankonguse.com/ 的很多文章被其它网站转载,但是转载时未声明文章来源或参考自 http://tiankonguse.com/ 网站 ...

随机推荐

  1. CC3200作为STA模式连接路由器sl_WlanConnect出现exception occured at:0xa72fcf6

    1. 先看下出错的提示 2. 出错的代码部分,现在问题是定位不到哪一行代码出问题,反正运行一段时间就进入了 lRetVal = sl_WlanConnect((signed , &secPar ...

  2. Python进程、线程、协程及IO多路复用

    详情戳击下方链接 Python之进程.线程.协程 python之IO多路复用

  3. 【个人训练】(ZOJ3983)Crusaders Quest

    题意分析 和祖玛类似的那种玩法.不过是限定了九个字符,问最好情况下有几次三连碰. 暴力穷举即可.具体的做法是,先把所有"成块"的字符记录下来,然后一个一个删,再继续这样子递归做下去 ...

  4. Kotlin怎样使用Android的Dagger2

    作者:Antonio Leiva 时间:Apr 11, 2017 原文链接:https://antonioleiva.com/dagger-android-kotlin/ 在Android上,创建去耦 ...

  5. final static 修饰(转载)

    static修饰符        static修饰符能够与属性.方法和内部类一起使用,表示静态的.类中的静态变量和静态方法能够与类名一起使用,不需要创建一个类的对象来访问该类的静态成员,所以,stat ...

  6. 深度学习-CNN tensorflow 可视化

    tf.summary模块的简介 在TensorFlow中,最常用的可视化方法有三种途径,分别为TensorFlow与OpenCv的混合编程.利用Matpltlib进行可视化.利用TensorFlow自 ...

  7. Ubuntu18.04 + CUDA9.0 + cuDNN7.3 + Tensorflow-gpu-1.12 + Jupyter Notebook深度学习环境配置

    目录 一.Ubuntu18.04 LTS系统的安装 1. 安装文件下载 2. 制作U盘安装镜像文件 3. 开始安装 二.设置软件源的国内镜像 1. 设置方法 2.关于ubuntu镜像的小知识 三.Nv ...

  8. Visual Studio 2014安装包

    点击下载

  9. LeetCode 21 ——合并两个有序链表

    1. 题目 2. 解答 新建一个带有哨兵结点的链表,依次比较两个有序链表的结点值,将较小值的结点插入到新链表后面.直到其中一个比较完毕,将另一个链表剩余的结点全部放到新链表最后面即可.最后,可以删除哨 ...

  10. visionpro halcon 哪个好

    visionpro halcon 哪个好 很多朋友会问到visionpro和halcon这两款机器视觉软件,到底学哪个好呢,今天众寻网就给大家讲一讲: 首先比较下两者的优缺点: halcon: 提供的 ...