过路费 
【问题描述】
在某个遥远的国家里,有 n 个城市。编号为 1,2,3,…,n。这个国家的政府修 建了 m 条双向道路,每条道路连接着两个城市。政府规定从城市 S 到城市 T 需 要收取的过路费为所经过城市之间道路长度的最大值。如:A 到 B 长度为 2,B 到 C 长度为 3,那么开车从 A 经过 B 到 C 需要上交的过路费为 3。 佳佳是个做生意的人,需要经常开车从任意一个城市到另外一个城市,因此 他需要频繁地上交过路费,由于忙于做生意,所以他无时间来寻找交过路费最低 的行驶路线。然而,当他交的过路费越多他的心情就变得越糟糕。作为秘书的你, 需要每次根据老板的起止城市,提供给他从开始城市到达目的城市,最少需要上 交多少过路费。 
【输入文件】
第一行是两个整数 n 和 m,分别表示城市的个数以及道路的条数。    接下来 m 行,每行包含三个整数 a,b,w(1≤a,b≤n,0≤w≤10^9),表示 a 与 b 之间有一条长度为 w 的道路。    接着有一行为一个整数 q,表示佳佳发出的询问个数。    再接下来 q 行,每一行包含两个整数 S,T(1≤S,T≤n,S≠T), 表示开始城 市 S 和目的城市 T。  
【输出文件】
输出文件共 q 行,每行一个整数,分别表示每个询问需要上交的最少过路费 用。输入数据保证所有的城市都是连通的。 
【样例输入】
4 5
1 2 10
1 3 20
1 4 100
2 4 30
3 4 10
2
1 4
4 1
【样例输出】
20
20  
【数据范围】
对于 30%的数据,满足 1≤ n≤1000,1≤m≤10000,1≤q≤100;
对于 50%的数据,满足 1≤ n≤10000,1≤m≤10000,1≤q≤10000;
对于 100%的数据,满足 1≤ n≤10000,1≤m≤100000,1≤q≤10000;

分析:

看到本题后,会先想到对于每对询问,二分两城市间道路路径最大值,将图中超过该最大值的边删去,求最短路径看两个城市是否是连通的,然后依据情况改变上下界。然而这样显然只能拿30分,我们需要想更高效的方法。

我们要先枚举询问,再对于每个询问用二分+最短路求解,这样很耗时间,如果能用较快的算法批量处理所有询问的答案,或者确定答案所在的范围就好了。于是我们想到最小生成树,你会发现在改图的最小生成树中,两点路径上的最大边是最小的,因为最小生成树要求两点间距离尽可能小,如果在a到b的两条路径的最大边分别为m,n,如果有m>n,则会选择n的那条而舍弃另外的路径。

由于最小生成树中两点间路径唯一,我们于是确定了两点间最大边最小的路径,然而问题来了,尽管知道这个最大边最小的路径,但我们怎么知道这条路径的最大边?将路径走一遍显然很慢,于是我们要进一步改进方法。我们发现已经求出最小生成树,本题就转化为求树上两点路径边的最大值,我们可以将边作为点,将其连接的两个点所在的子树作为新点的左右孩子,构成如下的图:

样例所给图的最小生成树构成的新图

建图要用并查集,按边权值的大小从小到大建边。由于从小到大建边,则其深度越大,点所代表的边权值越大,在此树中两点间路径只有一条,而它们的最近公共祖先必然在这个路径上且它深度在子树中最小,则一定是路径上所有边的最大值。于是本题被巧妙地转化为了LCA问题,然后用rmq解决即可。

LCA转rmq:先对树DFS,得到一个序列,并记录每个点的深度,用rmq求区间各点深度最小值,对于每个询问中的两点,我们可以知道它们在序列中的最先出现的位置,输出这两个位置形成区间的深度最小值即可,注意rmq时要记录深度最小点的编号。

代码:

program cost;
var
a,b,c:array[..,..]of longint;
v,w,p,q,r,d:array[..]of longint;
h:array[..,..]of longint;
f:array[..]of longint;
pl:array[..]of longint;
n,i,m,x,y,tot,s,j,u,k,x1,y1,t:longint;
function find(x:longint):longint;
var i,j,k:longint;
begin
i:=x; j:=x;
while f[i]<>i do i:=f[i];
while i<>j do
begin
k:=f[j]; f[j]:=i; j:=k;
end;
end;
function max(x,y:longint):longint;
begin
if x>y then max:=x else max:=y;
end;
procedure qsort(l,r:longint);
var i,j,mid,t:longint;
begin
i:=l; j:=r; mid:=v[(i+j) div ];
repeat
while v[i]<mid do inc(i);
while mid<v[j] do dec(j);
if i<=j then
begin
t:=v[i]; v[i]:=v[j]; v[j]:=t;
t:=a[i,]; a[i,]:=a[j,]; a[j,]:=t;
t:=a[i,]; a[i,]:=a[j,]; a[j,]:=t;
inc(i);dec(j);
end;
until i>j;
if i<r then qsort(i,r);
if l<j then qsort(l,j);
end;
procedure dfs(x,y:longint);
var i:longint;
begin
tot:=tot+; q[tot]:=x; d[x]:=y;
if c[x,]> then begin dfs(c[x,],y+); tot:=tot+; q[tot]:=x; end;
if c[x,]> then begin dfs(c[x,],y+); tot:=tot+; q[tot]:=x; end;
end;
begin
assign(input,'cost.in');
reset(input);
assign(output,'cost.out');
rewrite(output);
readln(n,m);
for i:= to m do
readln(a[i,],a[i,],v[i]);
qsort(,m);
for i:= to n do
f[i]:=i;
for i:= to m do
begin
x:=find(a[i,]); y:=find(a[i,]);
if x<>y then
begin
s:=s+; b[s,]:=a[i,]; b[s,]:=a[i,]; w[s]:=v[i];
f[y]:=x;
end;
if s=n- then break;
end;
for i:= to n+s do f[i]:=i;
for i:= to s do
begin
x:=find(b[i,]); y:=find(b[i,]);
f[x]:=n+i; f[y]:=n+i; c[n+i,]:=x; c[n+i,]:=y; p[n+i]:=w[i];
end;
dfs(n+s,);
k:=tot;
for i:= to k do h[,i]:=q[i];
pl[]:=;
for i:= to trunc(ln(k)/ln()) do pl[i]:=pl[i-]*;
for i:= to trunc(ln(k)/ln()) do
for j:= to k+-*i do
begin
x:=h[i-,j]; y:=h[i-,j+pl[i-]];
if d[x]<d[y] then h[i,j]:=x else h[i,j]:=y;
end;
for i:= to k do if r[q[i]]= then r[q[i]]:=i;
readln(u);
for i:= to u do
begin
readln(x,y); x:=r[x]; y:=r[y];
if x>y then begin t:=x; x:=y; y:=t; end;
j:=trunc(ln(y-x+)/ln());
x1:=h[j,x]; y1:=h[j,y-pl[j]+];
if d[x1]<d[y1] then writeln(p[x1]) else writeln(p[y1]);
end;
close(input); close(output);
end.

习题:过路费(kruskal+并查集+LCA)的更多相关文章

  1. TOJ 2815 Connect them (kruskal+并查集)

    描述 You have n computers numbered from 1 to n and you want to connect them to make a small local area ...

  2. hdu 2874 Connections between cities (并查集+LCA)

    Connections between cities Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (J ...

  3. hdu6074[并查集+LCA+思维] 2017多校4

    看了标答感觉思路清晰了许多,用并查集来维护全联通块的点数和边权和. 用另一个up[]数组(也是并查集)来保证每条边不会被重复附权值,这样我们只要将询问按权值从小到大排序,一定能的到最小的边权和与联通块 ...

  4. Minimum Spanning Tree.prim/kruskal(并查集)

    开始了最小生成树,以简单应用为例hoj1323,1232(求连通分支数,直接并查集即可) prim(n*n) 一般用于稠密图,而Kruskal(m*log(m))用于系稀疏图 #include< ...

  5. Connect the Campus (Uva 10397 Prim || Kruskal + 并查集)

    题意:给出n个点的坐标,要把n个点连通,使得总距离最小,可是有m对点已经连接,输入m,和m组a和b,表示a和b两点已经连接. 思路:两种做法.(1)用prim算法时,输入a,b.令mp[a][b]=0 ...

  6. Gym 100814C Connecting Graph 并查集+LCA

    Description standard input/output Statements Alex is known to be very clever, but Walter does not be ...

  7. Network-POJ3694并查集+LCA

    Network Time Limit: 5000MS   Memory Limit: 65536K       Description A network administrator manages ...

  8. [并查集+LCA USACO18OPEN ] Disruption

    https://www.luogu.org/problemnew/show/P4374 一看这道题就是一个妙题,然后题解什么树链剖分...珂朵莉树... 还不如并查集来的实在!我们知道并查集本来就是路 ...

  9. Mobile Phone Network CodeForces - 1023F(并查集lca+修改环)

    题意: 就是有几个点,你掌控了几条路,你的商业对手也掌控了几条路,然后你想让游客都把你的所有路都走完,那么你就有钱了,但你又想挣的钱最多,真是的过分..哈哈 游客肯定要对比一下你的对手的路 看看那个便 ...

随机推荐

  1. UVA Live Archive 4015 Cave (树形dp,分组背包)

    和Heroes Of Might And Magic 相似,题目的询问是dp的一个副产物. 距离是不好表示成状态的,但是可以换一个角度想,如果知道了从一个点向子树走k个结点的最短距离, 那么就可以回答 ...

  2. 【洛谷2152】[SDOI2009] SuperGCD(Python好题)

    点此看题面 大致题意: 给你两个长度\(\le10000\)的正整数,让你求它们的\(gcd\). Python​ 高精请绕道. 这题的正解应该是Python. 对于这种高精题,肯定是Python最方 ...

  3. python_37_文件修改

    f=open('yesterday','r',encoding='utf-8') f_new=open('yesterday_update','w',encoding='utf-8') for lin ...

  4. 牛客小白月赛5 A 无关(relationship) 【容斥原理】【数据范围处理】

    题目链接:https://www.nowcoder.com/acm/contest/135/A 题目描述 若一个集合A内所有的元素都不是正整数N的因数,则称N与集合A无关.   给出一个含有k个元素的 ...

  5. ElasticSearch High Level REST API【2】搜索查询

    如下为一段带有分页的简单搜索查询示例 在search搜索中大部分的搜索条件添加都可通过设置SearchSourceBuilder来实现,然后将SearchSourceBuilder RestHighL ...

  6. 【Django】URL中传递中文的问题

     开发环境:Ubuntu16.04+Django 1.11.9+Python2.7 在开发中,在做查找某些信息这个功能的时候,遇到的一个问题.需要在URL中传递查找的关键字,当关键字为中文的时候,并不 ...

  7. OpenFaceswap 入门教程(1):软件安装篇

    ---恢复内容开始--- 众多换脸软件中,DeepFaceLab其实是安装和使用最方便,更新最快的,但是由于其没有可是化界面,对于很新手来说,可能入门还是有点难度.那么今天就来介绍一款操作极其直观和简 ...

  8. 解决Uva网站打开慢的问题

    https://blog.csdn.net/richenyunqi/article/details/80990535

  9. requests中文页面乱码解决方案【转】

    requests中文页面乱码解决方案!   请给作者点赞 --> 原文链接 Python中文乱码,是一个很大的坑,自己不知道在这里遇到多少问题了.还好通过自己不断的总结,现在遇到乱码的情况越来越 ...

  10. unity安装记录

    官网直接下载(http://unity3d.com/cn/) 下载完后,会要求输入账号密码.我是先在官网进行一个账号注册,然后登陆即可. 首先会要你输入一个已有的邮箱,进行认证.进入自己邮箱,点击链接 ...