目錄node
luogu
很久沒寫博客了,水一篇波。c++
枚舉最長鏈的邊,刪除後代價爲(最長鏈-邊權,不通過這條邊的鏈)的最大值。
不通過某條邊的最大值要用線段樹維護補集。
複雜度\(O(nlog^2n)\)數據結構
二分答案,刪除的邊爲\(>mid\)的鏈的交集。
用樹上查分維護交集。
最後在交集中找個最大的邊刪除就行了。
複雜度\(O(nlogn)\)spa
思路2,複雜度小,好寫,簡單,細節少。
思路1,複雜度高,碼量大,細節多,並非呢麼好想。
因此並非很建議寫第一種。
但他靠着樹剖的小常數跑過了樹上差分(至少我是這樣,1.9s->1.2s)。code
#include <bits/stdc++.h> using namespace std; const int _=5e5+7; int read() { int x=0,f=1;char s=getchar(); for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1; for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0'; return x*f; } int n,m,ans,u[_],v[_],dsr[_],w[_]; struct node { int v,nxt,q,w; }e[_<<1]; int head[_],tot; void add(int u,int v,int q) { e[++tot].v=v; e[tot].q=q; e[tot].nxt=head[u]; head[u]=tot; } int f[_],dep[_],siz[_],son[_],top[_],idx[_],dis[_],nb[_],cnt; void dfs1(int u,int fa) { dep[u]=dep[fa]+1; f[u]=fa; siz[u]=1; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(v==fa) continue; w[v]=e[i].q; dis[v]=dis[u]+e[i].q; dfs1(v,u); siz[u]+=siz[v]; if(siz[son[u]]<siz[v]) son[u]=v; } } void dfs2(int u,int topf) { top[u]=topf; idx[u]=++cnt; nb[cnt]=u; if(!son[u]) return; dfs2(son[u],topf); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(!idx[v]) dfs2(v,v); } } namespace seg_tree { #define ls rt<<1 #define rs rt<<1|1 int ma[_<<2],lazy[_]; void tag(int rt,int val) {ma[rt]=max(ma[rt],val);lazy[rt]=max(lazy[rt],val);} void pushdown(int rt) {tag(ls,lazy[rt]);tag(rs,lazy[rt]);} void modify(int L,int R,int val,int l,int r,int rt) { if(L>R) return; if(L<=l&&r<=R) return tag(rt,val); int mid=(l+r)>>1; pushdown(rt); if(L<=mid) modify(L,R,val,l,mid,ls); if(R>mid) modify(L,R,val,mid+1,r,rs); ma[rt]=max(ma[ls],ma[rs]); } void dfs(int l,int r,int rt) { if(l==r) return void(dsr[nb[l]]=ma[rt]); int mid=(l+r)>>1; pushdown(rt); if(l<=mid) dfs(l,mid,ls); if(r>mid) dfs(mid+1,r,rs); } } int lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); x=f[top[x]]; } return dep[x]<dep[y]?x:y; } void QQ(int x,int y,int val) { int las=n; while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); seg_tree::modify(idx[x]+1,las,val,1,n,1); las=idx[top[x]]-1; x=f[top[x]]; } if(dep[x]<dep[y]) swap(x,y); seg_tree::modify(idx[x]+1,las,val,1,n,1); seg_tree::modify(1,idx[y],val,1,n,1); } int main() { n=read(),m=read(); for(int i=1,x,y,q;i<n;++i) { x=read(),y=read(),q=read(); add(x,y,q),add(y,x,q); } for(int i=1;i<=m;++i) { u[i]=read(),v[i]=read(); if(u[i]==v[i]) m--,i--; } dfs1(1,0),dfs2(1,1); int id=0,ma=0; for(int i=1;i<=m;++i) { int val=dis[u[i]]+dis[v[i]]-2*dis[lca(u[i],v[i])]; QQ(u[i],v[i],val); if(ma<val) id=i,ma=val; } if(!id) return printf("0\n"),0; seg_tree::dfs(1,n,1); int x=u[id],y=v[id],ans=0x3f3f3f3f; while(x!=y) { if(dep[x]<dep[y]) swap(x,y); ans=min(ans,max(dsr[x],ma-w[x])); x=f[x]; } cout<<ans<<"\n"; return 0; }
#include <bits/stdc++.h> using namespace std; const int _=5e5+7; int read() { int x=0,f=1;char s=getchar(); for(;s>'9'||s<'0';s=getchar()) if(s=='-') f=-1; for(;s>='0'&&s<='9';s=getchar()) x=x*10+s-'0'; return x*f; } int n,m,ans,u[_],v[_],LCA[_],len[_],the_biggest,w[_]; struct node { int v,nxt,q; }e[_<<1]; int head[_],tot; void add(int u,int v,int q) { e[++tot].v=v; e[tot].q=q; e[tot].nxt=head[u]; head[u]=tot; } int f[_],dep[_],siz[_],son[_],dis[_],top[_],cnt; void dfs1(int u,int fa) { dep[u]=dep[fa]+1,f[u]=fa,siz[u]=1; for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(v==fa) continue; w[v]=e[i].q; dis[v]=dis[u]+e[i].q; dfs1(v,u); siz[u]+=siz[v]; if(siz[son[u]]<siz[v]) son[u]=v; } } void dfs2(int u,int topf) { top[u]=topf; if(!son[u]) return; dfs2(son[u],topf); for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(!top[v]) dfs2(v,v); } } int lca(int x,int y) { while(top[x]!=top[y]) { if(dep[top[x]]<dep[top[y]]) swap(x,y); x=f[top[x]]; } return dep[x]<dep[y]?x:y; } int dsr[_],js; void dfs(int u,int fa) { for(int i=head[u];i;i=e[i].nxt) { int v=e[i].v; if(v==fa) continue; dfs(v,u); dsr[u]+=dsr[v]; } } bool check(int mid) { js=0; for(int i=0;i<=n;++i) dsr[i]=0; for(int i=1;i<=m;++i) { if(len[i]<=mid) continue; dsr[LCA[i]]-=2; dsr[u[i]]++; dsr[v[i]]++; ++js; } dfs(1,0); int ma=0x3f3f3f3f; for(int i=1;i<=n;++i) if(dsr[i]==js) ma=min(ma,the_biggest-w[i]); return ma<=mid; } int main() { n=read(),m=read(); for(int i=1,x,y,q;i<n;++i) { x=read(),y=read(),q=read(); add(x,y,q),add(y,x,q); } dfs1(1,0),dfs2(1,1); for(int i=1;i<=m;++i) { u[i]=read(),v[i]=read(),LCA[i]=lca(u[i],v[i]); len[i]=dis[u[i]]+dis[v[i]]-2*dis[LCA[i]]; the_biggest=max(the_biggest,len[i]); } int l=0,r=the_biggest,ans=0; while(l<=r) { int mid=(l+r)>>1; if(check(mid)) ans=mid,r=mid-1; else l=mid+1; } cout<<ans<<"\n"; return 0; }