在某个遥远的国家里,有 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. kettle 遇到 解决Incorrect integer value: '' for column 'id' at row 1 完美解决-费元星

    最近自己在测试一个开源的程序,测试中发现.该程序都添加和更新的时候回出现 Incorrect integer value: '' for column 'id' at row 1类是的错误! 后来我自 ...

  2. springmvc基础篇—拆分配置文件

    一般来讲,在企业实际项目中通常会将配置文件设置为两个:spring-mvc.xml.beans.xml,各自管各自的内容,方便管理. 一.在src下增加如下配置文件: <?xml version ...

  3. 数据库学习(三) sql语句中添加函数 to_char,round,连接符||

    ** to char 是把日期或数字转换为字符串  to date 是把字符串转换为数据库中得日期类型  参考资料:https://www.cnblogs.com/hllnj2008/p/533296 ...

  4. 贝叶斯网(1)尝试用Netica搭建简单的贝叶斯网并使用贝叶斯公式解释各个bar的结果

    近来对贝叶斯网十分感兴趣,按照博客<读懂概率图模型:你需要从基本概念和参数估计开始>给出的第一个例子,试着搭建了一个student网. (1)点击绿F,对条件概率表予以输入(包括两个祖先节 ...

  5. java生成唯一的id编号

    GUID是一个128位长的数字,一般用16进制表示.算法的核心思想是结合机器的网卡.当地时间.一个随即数来生成GUID.从理论上讲,如果一台机器每秒产生10000000个GUID,则可以保证(概率意义 ...

  6. P1559 运动员最佳匹配问题

    题目描述 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势:Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势 ...

  7. hdu3068最长回文(Manacher算法)

    简单来说这是个很水的东西.有点dp的思想吧.推荐两个博客,很详细. http://blog.csdn.net/xingyeyongheng/article/details/9310555 http:/ ...

  8. 算法学习——kruskal重构树

    kruskal重构树是一个比较冷门的数据结构. 其实可以看做一种最小生成树的表现形式. 在普通的kruskal中,如果一条边连接了在2个不同集合中的点的话,我们将合并这2个点所在集合. 而在krusk ...

  9. [Leetcode] word break 拆分词语

    Given a string s and a dictionary of words dict, determine if s can be segmented into a space-separa ...

  10. uva10884 Persephone

    题目戳这里. 找规律. 每一列占据的格子一定是一段区间: 相邻列之间的区间有交. 上界先增后减,下界先减后增. \(f_{i,j,k,0/1,0/1}\)表示考虑前\(i\)列,第\(i\)列,上界为 ...