公元 2044 年,人类进入了宇宙纪元。ios
L 国有 n 个星球,还有 n-1 条双向航道,每条航道创建在两个星球之间,这 n-1 条git
航道连通了 L 国的全部星球。ui
小 P 掌管一家物流公司,该公司有不少个运输计划,每一个运输计划形如:有一艘物spa
流飞船须要从 ui 号星球沿最快的宇航路径飞行到 vi 号星球去。显然,飞船驶过一条航道 是须要时间的,对于航道 j,任意飞船驶过它所花费的时间为 tj,而且任意两艘飞船之 间不会产生任何干扰。blog
为了鼓励科技创新,L 国国王赞成小 P 的物流公司参与 L 国的航道建设,即容许小 P 把某一条航道改形成虫洞,飞船驶过虫洞不消耗时间。get
在虫洞的建设完成前小 P 的物流公司就预接了 m 个运输计划。在虫洞建设完成后, 这 m 个运输计划会同时开始,全部飞船一块儿出发。当这 m 个运输计划都完成时,小 P 的 物流公司的阶段性工做就完成了。string
若是小 P 能够自由选择将哪一条航道改形成虫洞,试求出小 P 的物流公司完成阶段 性工做所须要的最短期是多少?it
其实挺简单的……跟保卫王国什么的无法比……io
题意就是给你几条树上路径,有一次删除边权的机会,最小化它们的最大长度。“最大值最小”显然二分啊。class
考虑怎么check,首先若是二分出的$ans \ge $最长路径长度那么必定是合法的,不过没什么用,由于彻底能够把二分右端点设为最长路径长度。
咱们能够无视长度$\leq ans$的路径,那么接下来要作的,就是利用删除边权操做在答案中消去最长路径长度$-ans$这么大(设为w)的长度。在剩下的路径中,若是存在一条这些路径的公共边知足边权$\ge w$,就能够断定为合法的。
求路径的公共边能够转化为求树边覆盖次数,树上差分板子,注意对于边的差分是x++,y++,lca-=2。
而后路径长什么的直接lca求解便可。
因为它是一道有尊严的D2T3,因此确定会防AK。卡一下二分左右边界能够苟过去= =。
#include<cstdio> #include<iostream> #include<cstring> #define pa pair<int,int> #define re register using namespace std; const int L=1<<20|1; char buffer[L],*S,*T; #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) inline int read() { int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-'0',ch=getchar(); return x*f; } const int N=3e5+5; int n,m,to[N<<1],head[N],nxt[N<<1],tot,w[N<<1]; int size[N],son[N],top[N],fa[N],dep[N],dis[N]; pa p[N]; int D[N],_lca[N],dif[N],maxw; inline void add(int x,int y,int z) { to[++tot]=y; nxt[tot]=head[x]; head[x]=tot; w[tot]=z; } void dfs1(int x,int f) { fa[x]=f;dep[x]=dep[f]+1;size[x]=1; for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(y==f)continue; dis[y]=dis[x]+w[i]; dfs1(y,x); size[x]+=size[y]; if(size[y]>size[son[x]])son[x]=y; } } void dfs2(int x,int Top) { top[x]=Top; if(son[x])dfs2(son[x],Top); for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(top[y])continue; dfs2(y,y); } } inline int lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); return x; } void dfs(int x) { for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(y==fa[x])continue; dfs(y); dif[x]+=dif[y]; } } bool judge(int x,int cnt,int len) { for(int i=head[x];i;i=nxt[i]) { int y=to[i]; if(y==fa[x])continue; if(dif[y]==cnt&&w[i]>=len)return 1; if(judge(y,cnt,len))return 1; } return 0; } inline bool check(int val) { if(maxw<=val)return 1; for(re int i=1;i<=n;i++)dif[i]=0; int cnt=0; for(re int i=1;i<=m;i++) { if(D[i]<=val)continue; cnt++; dif[p[i].first]++;dif[p[i].second]++; dif[_lca[i]]-=2; } dfs(1); return judge(1,cnt,maxw-val); } int main() { n=read();m=read(); int maxe=0; for(re int i=1;i<n;i++) { int x=read(),y=read(),z=read(); add(x,y,z);add(y,x,z); maxe=max(maxe,z); } dfs1(1,0);dfs2(1,1); for(re int i=1;i<=m;i++) { int x=read(),y=read(),LCA=lca(x,y); p[i]=make_pair(x,y); D[i]=dis[x]+dis[y]-2*dis[LCA]; maxw=max(maxw,D[i]); _lca[i]=LCA; } int l=maxw-maxe,r=maxw,ans=r; while(l<=r) { int mid=l+r>>1; if(check(mid))ans=mid,r=mid-1; else l=mid+1; } printf("%d\n",ans); return 0; }