题意:一棵有边权的树上有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一遍即可
贴个两年前写的代码
1 var f:array[1..300000,0..19]of longint; 2 head,vet,next,dep,fa,val,x,y,z,a,b,r,cnt,size,len,c,dis:array[1..700000]of longint; 3 n,m,i,left,right,mid,last,tot,tmp,maxw,maxans:longint; 4 5 procedure add(a,b,c:longint); 6 begin 7 inc(tot); 8 next[tot]:=head[a]; 9 vet[tot]:=b; 10 len[tot]:=c; 11 head[a]:=tot; 12 end; 13 14 procedure dfs(u,father:longint); 15 var e,v,i:longint; 16 begin 17 for i:=1 to 19 do 18 begin 19 if dep[u]<1<<i then break; 20 f[u,i]:=f[f[u,i-1],i-1]; 21 end; 22 size[u]:=1; 23 e:=head[u]; 24 while e<>0 do 25 begin 26 v:=vet[e]; 27 if v<>fa[u] then 28 begin 29 f[v,0]:=u; 30 fa[v]:=u; 31 dep[v]:=dep[u]+1; 32 dis[v]:=dis[u]+len[e]; 33 dfs(v,u); 34 size[u]:=size[u]+size[v]; 35 end; 36 e:=next[e]; 37 end; 38 end; 39 40 procedure swap(var x,y:longint); 41 var t:longint; 42 begin 43 t:=x; x:=y; y:=t; 44 end; 45 46 function lca(x,y:longint):longint; 47 var i,d:longint; 48 begin 49 if dep[x]<dep[y] then swap(x,y); 50 d:=dep[x]-dep[y]; 51 for i:=0 to 19 do 52 if d and (1<<i)>0 then x:=f[x,i]; 53 for i:=19 downto 0 do 54 if f[x,i]<>f[y,i] then 55 begin 56 x:=f[x,i]; y:=f[y,i]; 57 end; 58 if x=y then exit(x); 59 exit(f[x,0]); 60 end; 61 62 function max(x,y:longint):longint; 63 begin 64 if x>y then exit(x); 65 exit(y); 66 end; 67 68 function dfs2(u:longint):longint; 69 var e,v:longint; 70 begin 71 e:=head[u]; 72 while e<>0 do 73 begin 74 v:=vet[e]; 75 if v<>fa[u] then cnt[u]:=cnt[u]+dfs2(v); 76 e:=next[e]; 77 end; 78 if cnt[u]=tmp then maxw:=max(maxw,val[u]); 79 exit(cnt[u]); 80 end; 81 82 function isok(k:longint):boolean; 83 var i:longint; 84 begin 85 maxans:=0; maxw:=0; tmp:=0; 86 fillchar(cnt,sizeof(cnt),0); 87 for i:=1 to n do 88 if c[i]>k then 89 begin 90 maxans:=max(maxans,c[i]); 91 inc(cnt[a[i]]); 92 inc(cnt[b[i]]); 93 cnt[r[i]]:=cnt[r[i]]-2; 94 inc(tmp); 95 end; 96 97 dfs2(1); 98 if maxans-maxw<=k then exit(true); 99 exit(false); 100 end; 101 102 begin 103 104 readln(n,m); 105 for i:=1 to n-1 do 106 begin 107 readln(x[i],y[i],z[i]); 108 add(x[i],y[i],z[i]); 109 add(y[i],x[i],z[i]); 110 end; 111 dfs(1,0); 112 for i:=1 to m do 113 begin 114 readln(a[i],b[i]); 115 r[i]:=lca(a[i],b[i]); 116 c[i]:=dis[a[i]]+dis[b[i]]-dis[r[i]]*2; 117 end; 118 119 for i:=1 to n-1 do 120 if dep[x[i]]>dep[y[i]] then val[x[i]]:=z[i] 121 else val[y[i]]:=z[i]; 122 123 left:=0; right:=50000000; 124 while left<=right do 125 begin 126 mid:=(left+right)>>1; 127 if isok(mid) then begin last:=mid; right:=mid-1; end 128 else left:=mid+1; 129 end; 130 writeln(last); 131 132 133 end.