在一颗有边权的树上有m条路径,清零一条边的边权使得m条路径的最大值最小。 输出这个最大值
显然 要遍历这m条路的最长路(如果最长路有多条随意遍历一条即可)
因为树上距离不修改 那么用前缀和维护树上路径长度可以少一个log
然后遍历最长路的每一条边 ans=min(ans,max(最长路的长度-这条路的长度,不经过这条边的最长路长度)
所以现在需要维护的是不经过这条边的最长路长度
可以遍历m 将不在这条路径上的所有边 维护一个值(就是这条路径的长度) 用线段树维护最大值即可
#include<bits/stdc++.h> using namespace std; #define rep(i,a,b) for(int i=(a);i<=(b);i++) #define repp(i,a,b) for(int i=(a);i>=(b);--i) #define ll long long #define see(x) (cerr<<(#x)<<'='<<(x)<<endl) #define inf 0x3f3f3f3f #define CLR(A,v) memset(A,v,sizeof A) ////////////////////////////////// const int N=2e6+10; int maxx[N<<2],col[N<<2],n,m,maxans[N],d[N],maxbian,flagx,flagy,val[N]; void build(int l,int r,int pos) { if(l==r){maxx[pos]=0;return;} int m=(l+r)>>1; build(l,m,pos<<1);build(m+1,r,pos<<1|1); maxx[pos]=max(maxx[pos<<1],maxx[pos<<1|1]); } void down(int pos) { if(!col[pos])return ; col[pos<<1]=max(col[pos<<1],col[pos]); col[pos<<1|1]=max(col[pos<<1|1],col[pos]); maxx[pos<<1]=max(maxx[pos<<1],col[pos]); maxx[pos<<1|1]=max(maxx[pos<<1|1],col[pos]); col[pos]=0; } void upsum(int L,int R,int v,int l,int r,int pos) { if(L<=l&&r<=R){maxx[pos]=max(maxx[pos],v);col[pos]=max(col[pos],v);return ;} int m=(l+r)>>1;down(pos); if(L<=m)upsum(L,R,v,l,m,pos<<1); if(R>m)upsum(L,R,v,m+1,r,pos<<1|1); maxx[pos]=max(maxx[pos<<1],maxx[pos<<1|1]); } void qmax(int l,int r,int pos) { if(l==r){maxans[l]=maxx[pos];return ;} int m=(l+r)>>1;down(pos); qmax(l,m,pos<<1); qmax(m+1,r,pos<<1|1); } int qmaxx(int x,int l,int r,int pos) { if(l==r)return maxx[pos]; int m=(l+r)>>1;down(pos); if(x<=m)return qmaxx(x,l,m,pos<<1); else return qmaxx(x,m+1,r,pos<<1|1); } int id[N],top[N],fa[N],dep[N],son[N],siz[N],pre[N],ncnt,pos,head[N]; struct Edge{int to,nex;}edge[N<<1]; void add(int a,int b){edge[++pos]=Edge{b,head[a]};head[a]=pos;} void dfs1(int x,int f) { fa[x]=f;dep[x]=dep[f]+1;siz[x]=1;son[x]=0; for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to;if(v==f)continue; dfs1(v,x);siz[x]+=siz[v]; if(siz[son[x]]<siz[v])son[x]=v; } } void dfs2(int x,int topf) { top[x]=topf;id[x]=++ncnt;pre[ncnt]=x; if(son[x])dfs2(son[x],topf); for(int i=head[x];i;i=edge[i].nex) { int v=edge[i].to;if(v==fa[x]||v==son[x])continue; dfs2(v,v); } } int u[N],v[N],w[N]; int Qdis(int x,int y) { int ans=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); ans+=d[id[x]]-d[id[top[x]]-1]; x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); ans+=d[id[y]]-d[id[x]]; return ans; } struct node { int x,y; }s[N]; void UPsum(int x,int y,int v) { int cnt=0; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]])swap(x,y); s[++cnt].x=id[top[x]],s[cnt].y=id[x]; x=fa[top[x]]; } if(dep[x]>dep[y])swap(x,y); s[++cnt].x=id[x]+1,s[cnt].y=id[y]; sort(s+1,s+1+cnt,[](node a,node b){return a.x<b.x||a.x==b.x&&a.y<b.y;}); if(s[1].x>1)upsum(1,s[1].x-1,v,1,n,1); if(s[cnt].y<n)upsum(s[cnt].y+1,n,v,1,n,1); rep(i,1,cnt-1) if(s[i].y+1<=s[i+1].x-1)upsum(s[i].y+1,s[i+1].x-1,v,1,n,1); } int getans(int x,int y) { int ans=inf; if(x==y)return 0; while(x!=y) { if(dep[x]<dep[y])swap(x,y); ans=min(ans,max(maxbian-val[x],maxans[id[x]])); x=fa[x]; } return ans; } int main() { scanf("%d%d",&n,&m); rep(i,1,n-1) scanf("%d%d%d",&u[i],&v[i],&w[i]),add(u[i],v[i]),add(v[i],u[i]); dfs1(1,1); dfs2(1,1); build(1,n,1); rep(i,1,n-1) { if(dep[u[i]]<dep[v[i]])swap(u[i],v[i]); val[u[i]]=d[id[u[i]]]=w[i]; } rep(i,1,n) d[i]+=d[i-1]; while(m--) { int x,y; scanf("%d%d",&x,&y); int temp=Qdis(x,y); if(temp>maxbian)maxbian=temp,flagx=x,flagy=y; UPsum(x,y,temp); } qmax(1,n,1); cout<<getans(flagx,flagy); return 0; }