题解:二分答案,标记长度>mid的路径,找到最长的被所有标记路径覆盖的边,如果maxpath-maxedge<=mid就符合
#include<iostream> #include<cstdio> #include<cstring> using namespace std; const int maxn=300009; const int oo=1000000000; int n,m; int cntedge; int head[maxn]; int to[maxn<<1],nex[maxn<<1],dist[maxn<<1]; void Addedge(int x,int y,int z){ nex[++cntedge]=head[x]; to[cntedge]=y; dist[cntedge]=z; head[x]=cntedge; } int f[maxn][20]; int fdist[maxn]; int dep[maxn]; int d[maxn]; void Dfs(int now,int fa){ f[now][0]=fa; dep[now]=dep[fa]+1; for(int i=head[now];i;i=nex[i]){ if(to[i]==fa)continue; fdist[to[i]]=dist[i]; d[to[i]]=d[now]+dist[i]; Dfs(to[i],now); } } void LCAinit(){ for(int j=1;j<=19;++j){ for(int i=1;i<=n;++i){ f[i][j]=f[f[i][j-1]][j-1]; } } } int Getlca(int u,int v){ if(dep[u]<dep[v])swap(u,v); for(int j=19;j>=0;--j){ if(dep[f[u][j]]>=dep[v])u=f[u][j]; } if(u==v)return u; for(int j=19;j>=0;--j){ if(f[u][j]!=f[v][j]){ u=f[u][j];v=f[v][j]; } } return f[u][0]; } int g[maxn]; void Dp(int x,int fa){ for(int i=head[x];i;i=nex[i]){ if(to[i]==fa)continue; Dp(to[i],x); g[x]+=g[to[i]]; } } int rx[maxn],ry[maxn],lca[maxn],rd[maxn]; int maxlength; int l,r,mid,ans; void minit(){ maxlength=0; memset(d,0,sizeof(d)); memset(dep,0,sizeof(dep)); memset(f,0,sizeof(f)); memset(fdist,0,sizeof(fdist)); memset(head,0,sizeof(head)); cntedge=0; } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n-1;++i){ int x,y,z; scanf("%d%d%d",&x,&y,&z); Addedge(x,y,z); Addedge(y,x,z); } Dfs(1,0); LCAinit(); for(int i=1;i<=m;++i){ scanf("%d%d",&rx[i],&ry[i]); lca[i]=Getlca(rx[i],ry[i]); rd[i]=d[rx[i]]+d[ry[i]]-2*d[lca[i]]; maxlength=max(maxlength,rd[i]); } l=0;r=oo; while(l<=r){ mid=(l+r)>>1; memset(g,0,sizeof(g)); int invedge=0; for(int i=1;i<=m;++i){ if(rd[i]>mid){ g[rx[i]]++;g[ry[i]]++;g[lca[i]]-=2;++invedge; } } Dp(1,0); int maxedge=0; for(int i=2;i<=n;++i){ if(g[i]==invedge)maxedge=max(maxedge,fdist[i]); } if(maxlength-maxedge<=mid){ ans=mid;r=mid-1; }else{ l=mid+1; } } cout<<ans<<endl; return 0; }