luogu P2680
#include<bits/stdc++.h> #define RI register int #define MN 300008 using namespace std; struct node{ int x,y,lca,dis ; }ask[MN]; int comp(node xx,node yy){ return xx.dis<yy.dis; } int dep[MN],f[MN][21],dis[MN],n,head[MN],tot,k,ans,init[MN],cnt[MN]; struct tu{ int nxt,v,w; }e[MN<<1]; int l,r,m; void add(int x,int y,int z) { e[++tot].nxt=head[x]; e[tot].v=y; e[tot].w=z; head[x]=tot; } void dfs(int u,int fa , int dd) { dep[u]=dep[fa]+1; f[u][0]=fa ; init[u]=dd; for(RI i=1;(1<<i)<=dep[u];i++) f[u][i]=f[f[u][i-1]][i-1]; for(RI i=head[u];i;i=e[i].nxt) { if(e[i].v==fa)continue; dis[e[i].v]=dis[u]+e[i].w; dfs(e[i].v,u,e[i].w); } } int lca(int x,int y) { if(dep[x]>dep[y])swap(x,y); for(RI i=20;i>=0;i--) if(dep[y]-(1<<i)>=dep[x]) y=f[y][i]; if(x==y)return x; for(RI i=20;i>=0;i--) { if(f[x][i]==f[y][i])continue; x=f[x][i],y=f[y][i]; } return f[x][0]; } void search(int u,int fa) { for(RI i=head[u];i;i=e[i].nxt) { if(e[i].v==fa)continue; search(e[i].v,u); cnt[u]+=cnt[e[i].v]; } } bool pd(int x) { int num=0,now=0; for(RI i=1;i<=n;i++)cnt[i]=0; for(RI i=1;i<=m;i++) { if(ask[i].dis<=x)continue; cnt[ask[i].x]++;cnt[ask[i].y]++; cnt[ask[i].lca]-=2; num++; } search(1,0); for(RI i=1;i<=n;i++) { if(cnt[i]==num)now=max(now,init[i]); } return ask[m].dis-now<=x; } int main() { scanf("%d%d",&n,&m); for(RI i=1;i<n;i++) { int x,y,z; scanf("%d%d%d",&x,&y,&z); add(x,y,z);add(y,x,z); } dfs(1,0,0); for(RI i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); ask[i].lca=lca(x,y); r=max(r,(ask[i].dis=dis[x]+dis[y]-2*dis[ask[i].lca])); ask[i].x = x,ask[i].y = y; } sort(ask+1,ask+m+1,comp); int ans1=0; while(l<=r) { int mid=(l+r)>>1; if(pd(mid)){ ans1=mid;r=mid-1; } else l=mid+1; } printf("%d",ans1); } /*二分时间TT之后然后就需要判定在给定时间TT之内能否完成工作.怎么判定呢?虫洞是通过将某条边删去来减少路径的时间, 假设如果有m条路径的时间大于TT, 那么就需要将这mm条路径上的一条公共边删去, 使得这mm条路径时间都会少于TT.如果存在这么一条边则TT是合法的.*/
缘分让我们相遇乱世以外,
命运却要我们危难中相爱。
也许未来遥远在光年之外,
我愿守候未知里为你等待。