题意:一棵有边权的树上有m条路径,要求选择一条边使其边权变为0,使得最大路径长度最小

n,m<=300000

思路:直接求最优方案不可做,但检验对于某一个ans是否能有方案是可行的

取出所有总长度>ans的路径,求它们的交,取交集中长度最大的一条,设值为c[i],总长度最长的设为max

比较max-c[i]与ans的关系即可

路径求交因为是离线的,可以暴力树剖,也可以分类讨论维护路径交

但对于这个离线的问题,可以差分来做

对于路径(a[i],b[i]),设c[i]=lca

分为a[i]到lca,b[i]到lca两条路径

f[a[i]]++ f[b[i]]++ f[c[i]]=f[c[i]]-2

最后自底向下dfs一遍即可

贴个两年前写的代码

 var f:array[..,..]of longint;
head,vet,next,dep,fa,val,x,y,z,a,b,r,cnt,size,len,c,dis:array[..]of longint;
n,m,i,left,right,mid,last,tot,tmp,maxw,maxans:longint; procedure add(a,b,c:longint);
begin
inc(tot);
next[tot]:=head[a];
vet[tot]:=b;
len[tot]:=c;
head[a]:=tot;
end; procedure dfs(u,father:longint);
var e,v,i:longint;
begin
for i:= to do
begin
if dep[u]<<<i then break;
f[u,i]:=f[f[u,i-],i-];
end;
size[u]:=;
e:=head[u];
while e<> do
begin
v:=vet[e];
if v<>fa[u] then
begin
f[v,]:=u;
fa[v]:=u;
dep[v]:=dep[u]+;
dis[v]:=dis[u]+len[e];
dfs(v,u);
size[u]:=size[u]+size[v];
end;
e:=next[e];
end;
end; procedure swap(var x,y:longint);
var t:longint;
begin
t:=x; x:=y; y:=t;
end; function lca(x,y:longint):longint;
var i,d:longint;
begin
if dep[x]<dep[y] then swap(x,y);
d:=dep[x]-dep[y];
for i:= to do
if d and (<<i)> then x:=f[x,i];
for i:= downto do
if f[x,i]<>f[y,i] then
begin
x:=f[x,i]; y:=f[y,i];
end;
if x=y then exit(x);
exit(f[x,]);
end; function max(x,y:longint):longint;
begin
if x>y then exit(x);
exit(y);
end; function dfs2(u:longint):longint;
var e,v:longint;
begin
e:=head[u];
while e<> do
begin
v:=vet[e];
if v<>fa[u] then cnt[u]:=cnt[u]+dfs2(v);
e:=next[e];
end;
if cnt[u]=tmp then maxw:=max(maxw,val[u]);
exit(cnt[u]);
end; function isok(k:longint):boolean;
var i:longint;
begin
maxans:=; maxw:=; tmp:=;
fillchar(cnt,sizeof(cnt),);
for i:= to n do
if c[i]>k then
begin
maxans:=max(maxans,c[i]);
inc(cnt[a[i]]);
inc(cnt[b[i]]);
cnt[r[i]]:=cnt[r[i]]-;
inc(tmp);
end; dfs2();
if maxans-maxw<=k then exit(true);
exit(false);
end; begin readln(n,m);
for i:= to n- do
begin
readln(x[i],y[i],z[i]);
add(x[i],y[i],z[i]);
add(y[i],x[i],z[i]);
end;
dfs(,);
for i:= to m do
begin
readln(a[i],b[i]);
r[i]:=lca(a[i],b[i]);
c[i]:=dis[a[i]]+dis[b[i]]-dis[r[i]]*;
end; for i:= to n- do
if dep[x[i]]>dep[y[i]] then val[x[i]]:=z[i]
else val[y[i]]:=z[i]; left:=; right:=;
while left<=right do
begin
mid:=(left+right)>>;
if isok(mid) then begin last:=mid; right:=mid-; end
else left:=mid+;
end;
writeln(last); end.

最新文章

  1. SFC中的故障管理
  2. iOS--NSTimer设置定时器的两种方法
  3. c#根据公式进行自动计算 四个5加减乘除=4
  4. Java Data Type
  5. Unity2D多分辨率屏幕适配方案(转载)
  6. 使用Unity3D自带动画系统制作下雨效果
  7. OpenERP里面继承的用法
  8. 如何实现TWaver 3D颜色渐变
  9. js获取input上传文件名和后缀
  10. 使用github 的相关博客
  11. 图数据库-Neo4j使用
  12. python的函数学习2
  13. Java虚拟机JVM相关知识整理
  14. SSM-动态SQL
  15. Ymodem协议(参考STM32)
  16. mysql外键的三种关系
  17. 如何在Windows环境下安装JDK
  18. 8 -- 深入使用Spring -- 3...1 Resource实现类FileSystemResource
  19. 常用算法1 - 快速排序 &amp; 二分查找
  20. MySQL(二)索引背后的数据结构及算法原理

热门文章

  1. MVP架构模式
  2. Java 线程 —— Wait (等待)和 Notify(唤醒)
  3. 原型模式及php实现
  4. 一个简单的Java代码生成工具—根据数据源自动生成bean、dao、mapper.xml、service、serviceImpl
  5. js实现元素水平垂直居中
  6. Centos7 安装MongoDB的详细过程
  7. Laravel Excel模板导出-带图片
  8. 1.C#冒泡排序
  9. SQLServer锁的概述
  10. 如何手写一款KOA的中间件来实现断点续传